﻿/*
 * Rappelz: Endless Odyssey - The first free open source Rappelz server emulator
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rappelz.GameServer.Network;
using Rappelz.GameServer.Network.GameClient;
using Rappelz.GameServer.Database;
using System.Threading;
using Rappelz.GameServer.Network.AuthClient;
using Rappelz.GameServer.Scripting;

namespace Rappelz.GameServer
{
    public class Player : Creature, Inventory.InventoryEventReceiver, QuestEventHandler
    {

        public static Dictionary<string, TCPConnection> m_hsAccountList = new Dictionary<string, TCPConnection>();
        public static Dictionary<string, Player> m_hsPlayerList = new Dictionary<string, Player>();
        public static List<Player> s_vPlayerList = new List<Player>();
        public static List<int> m_hsAutoAccount = new List<int>();
        public static int s_nReturnLobbyId = 0;
        public static List<RappelzPair<int, TCPConnection>> s_vReturnLobbyConn = new List<RappelzPair<int, TCPConnection>>();
        public static object s_PlayerListlock = new object();
        public static long s_nItemIndex;
        public static long s_nSummonSID;
        public static long s_nPetSID;

        public class FavorInfo
        {
            public FavorInfo(int _id, int _favor)
            {
                favor_id = _id;
                favor = _favor;
            }

            public int favor_id;
            public int favor;
        }

        public enum BonusType : int
        {
            PCBang = 0,
            Stamina = 1,
            PremiumPCBang = 2,
            SummonStamina = 3,
            GrowthPotion = 4,
            Max = 5,
        }

        public class BonusInfo
        {
            public int type;//             Data           :   this+0x0, Member, Type: int, type
            public int rate;//             Data           :   this+0x4, Member, Type: int, 
            public long exp;//             Data           :   this+0x8, Member, Type: __int64, 
            public int jp;//             Data           :   this+0x10, Member, Type: int, 
        }


        public enum SummonStaminSaverType : int
        {
            SummonStaminaSaverNone = 0,
            SummonStaminaSaverWithoutPenalty = 1,
            SummonStaminaSaverWithPenalty = 2,
        }

        public enum ConditionInfo : int
        {
            ConditionGood = 0,
            ConditionAverage = 1,
            ConditionBad = 2,
        }

        public uint LogoutTimer
        {
            get { return m_nLogoutTimer; }
            set { m_nLogoutTimer = value; }
        }

        public static uint GetPlayerCount()
        {
            lock(m_hsAccountList)
            {
                return (uint)m_hsAccountList.Count;
            }
        }

        public static bool RegisterAccount(TCPConnection conn, string szAccount)
        {
            lock(m_hsAccountList)
            {
                m_hsAccountList.Add(szAccount, conn);
            }
            return true;
        }

        public static void UnRegisterAccount(string szAccount)
        {
            lock(m_hsAccountList)
            {
                if (m_hsAccountList.ContainsKey(szAccount))
                    m_hsAccountList.Remove(szAccount);
            }
        }

        public static TCPConnection GetConnectionByAccount(string szAccount)
        {
            lock(m_hsAccountList)
            {
                if(m_hsAccountList.ContainsKey(szAccount))
                    return m_hsAccountList[szAccount];
            }
            return null;
        }

        public override bool IsPlayer()
        {
            return true;
        }

        public bool CanLogoutNow()
        {
            bool result = true;

            if(GameRule.nLogoutTimer == 0)
                return true;

            if(m_bIsPK)
            {
                result = false;
            }
            else if(!IsInTown())
            {
//                 if ( c_fixed<10000>::operator>(&m_fImmoralPoint, &MORAL_LIMIT_10) || c_fixed<10000>::operator>_(&m_fImmoralPoint, &CRIME_LIMIT_10) )
//                     result = false;
//                 else
                    result = !GameRule.bLimitFieldLogout;
                if ( result )
                    return result;
            }
            uint v5 = (uint) Environment.TickCount;
            uint v6 = GameRule.nLogoutTimer + m_nLastLogoutRequestedTime;
            if ( (m_nLastLogoutRequestedTime == 0) || (v5 < v6) || (v5 > v6 + 1000) )
                return result;
            return result;
        }

//         Function       :   public static struct StructPlayer::iterator StructPlayer::get(unsigned int)
// Function       :   public bool StructPlayer::IsSkillCastable()
// Function       :   public bool StructPlayer::IsMagicCastable()

        public static void EraseReturnLobbyConnection(int conn_id)
        {
            lock(s_vReturnLobbyConn)
            {
                for(int i = 0; i < s_vReturnLobbyConn.Count; ++i)
                {
                    if(s_vReturnLobbyConn[i].First == conn_id)
                    {
                        s_vReturnLobbyConn.RemoveAt(i);
                        return;
                    }
                }
            }
        }

        public int SetReturnLobbyConnection(TCPConnection conn)
        {
            lock(s_vReturnLobbyConn)
            {
                Interlocked.Increment(ref s_nReturnLobbyId);
                s_vReturnLobbyConn.Add(new RappelzPair<int,TCPConnection>(s_nReturnLobbyId,conn));
                this.m_nReturnLobbyConnId = s_nReturnLobbyId;
            }
            return s_nReturnLobbyId;
        }

// Function       :   public static void StructPlayer::EraseFromAutoAccount(int)

        public static void AddToAutoAccountList(int nAccountId)
        {
            lock(m_hsAutoAccount)
            {
                if(!m_hsAutoAccount.Contains(nAccountId))
                    m_hsAutoAccount.Add(nAccountId);
            }
        }

// Function       :   public static void StructPlayer::ClearAutoAccountList()
        public static bool IsAutoAccount(int account_id)
        {
            return false;
        }
// Function       :   public static void StructPlayer::BindProperty()
        public static Player AllocPlayer()
        {
            Player np = MemoryPool.AllocPlayer();
            return np;
        }

        public static int FindPlayer(string szName)
        {
            lock(m_hsPlayerList)
            {
                if(m_hsPlayerList.ContainsKey(szName))
                    return m_hsPlayerList[szName].m_nUID;
            }
            return 0;
        }

        public static Player GetPlayer(string szName)
        {
            lock (m_hsPlayerList)
            {
                if (m_hsPlayerList.ContainsKey(szName))
                    return m_hsPlayerList[szName];
            }
            return null;
        }

// Function       :   public static void EraseFromPlayerList(const char *)
// Function       :   public static bool StructPlayer::RegisterAccount(struct IStreamSocketConnection *, const char *)
// Function       :   public static void StructPlayer::UnRegisterAccount(const char *)
// Function       :   public static struct IStreamSocketConnection * StructPlayer::GetConnectionByAccount(const char *)
        public static bool IsRegisteredAccount(string szAccount)
        {
            lock(m_hsAccountList)
            {
                if (m_hsAccountList.ContainsKey(szAccount))
                    return true;
            }
            return false;
        }
// Function       :   public static const bool StructPlayer::SetRegisteredConnectionByAccount(const char *, struct IStreamSocketConnection *)

        public static void DoEachPlayer(BaseObjectFunctor fn)
        {
            lock(s_PlayerListlock)
            {
                foreach (Player p in s_vPlayerList)
                {
                    fn.run(p);
                }
            }

        }

        public static void DoPlayer(uint handle, BaseObjectFunctor fn)
        {
            lock (s_PlayerListlock)
            {
                fn.run(GameObject.raw_get(handle));
            }
        }
// Function       :   public static volatile int & StructPlayer::GetPlayerCount()
// Function       :   public static const char * StructPlayer::GetPlayerName(const int)
// Function       :   public static void StructPlayer::RegisterPlayerName(const int, const char *)
// Function       :   public static void StructPlayer::ClearPlayerName()
// Function       :   public static __int64 StructPlayer::GetMaxItemUID()
        public static void SetMaxItemUID(long id)
        {
            s_nItemIndex = id;
        }

        public static void SetMaxPetSID(long id)
        {
            s_nPetSID = id;
        }

        public static void SetMaxSummonSID(int id)
        {
            s_nSummonSID = id;
        }
// Function       :   public static int StructPlayer::AllocSummonSID()
// Function       :   public static void StructPlayer::SetMaxPetSID(int)
// Function       :   public static int StructPlayer::AllocPetSID()

// Function       :   public int GetPlayerUID()

        public int GetAccountID()
        {
            return m_nAccountID;
        }

        public int AccountID
        {
            get { return m_nAccountID; }
            set { m_nAccountID = value; }
        }

        public string AccountName
        {
            get { return m_szAccountName; }
            set { m_szAccountName = value; }
        }

        public string GetAccountName()
        {
            return m_szAccountName;
        }

        public override int GetSID()
        {
            return m_nUID;
        }

        public int SID
        {
            get { return m_nUID; }
            set { m_nUID = value; }
        }


        public void Save(bool bOnlyCharacter)
        {
//             int v2; // ebp@0
//             StructPlayer *v3; // esi@1
//             unsigned int v4; // eax@2
//             unsigned int v5; // eax@4
//             bool v6; // zf@4
//             void *v7; // ecx@6
//             GameDBManager::DBProc *v8; // eax@7
//             StructSummon *v9; // eax@10
//             StructSummon *v10; // edi@10
//             void *v11; // eax@14
//             DB_UpdateSummon *v12; // ecx@14
//             GameDBManager::DBProc *v13; // eax@14
//             void *v14; // ecx@17
//             GameDBManager::DBProc *v15; // eax@18
//             StructItem *v16; // eax@24
//             StructItem *v17; // edi@24
//             void *v18; // ecx@26
//             GameDBManager::DBProc *v19; // eax@27
//             unsigned int v20; // ebx@31
//             StructItem *v21; // eax@32
//             StructItem *v22; // edi@32
//             void *v23; // ecx@34
//             GameDBManager::DBProc *v24; // eax@35
//             StructCreature **v25; // eax@40
//             bool v26; // al@41
//             std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *v27; // ecx@41
//             int v28; // esi@42
//             StructCreature **v29; // eax@43
//             unsigned int *_foSkill_8; // [sp+8h] [bp-2Ch]@0
//             std::_Container_base *_foSkill_12; // [sp+Ch] [bp-28h]@0
//             unsigned int *_foQuest; // [sp+10h] [bp-24h]@0
//             std::_Container_base *_foQuest_4; // [sp+14h] [bp-20h]@0
// 
// .text:004566B4 _foSkill        = StructPlayer::Save::__l29::mySkillFunctor ptr -34h
// .text:004566B4 _foQuest        = StructPlayer::Save::__l20::myQuestFunctor ptr -24h
// .text:004566B4 it              = std::_Vector_iterator<StructSummon *,std::allocator<StructSummon *> > ptr -1Ch
// .text:004566B4 i               = dword ptr -10h
// .text:004566B4 bOnlyCharacter  = byte ptr  4
// .text:004566B4 idx             = dword ptr  8
//             
// Typedef        :   StructPlayer::Save::__l20::myQuestFunctor, Type: struct StructPlayer::Save::__l20::myQuestFunctor
// Data           :   ebp Relative, [FFFFFFDC], Local, Type: struct StructPlayer::Save::__l20::myQuestFunctor, _foQuest
            int i;
            uint idx;
            uint ct;
// Typedef        :   StructPlayer::Save::__l29::mySkillFunctor, Type: struct StructPlayer::Save::__l29::mySkillFunctor
// Data           :   ebp Relative, [FFFFFFCC], Local, Type: struct StructPlayer::Save::__l29::mySkillFunctor, _foSkill
// Data           :   ebp Relative, [FFFFFFE4], Local, Type: class std::_Vector_iterator<StructSummon *,std::allocator<StructSummon *> >, it
// Data           :   ebp Relative, [FFFFFFE4], Local, Type: class std::_Vector_iterator<StructSummon *,std::allocator<StructSummon *> >, it
// 
            ct = Globals.GetArTime();

            if (this.IsLoginComplete())
            {
                if (this.m_nLogoutTime == 0 || this.m_nLogoutTime >=this.m_nLastSaveTime)
                {
                    this.m_nLastExpSaveTime = ct;
                    if (!bOnlyCharacter)
                        this.m_nLastSaveTime = ct;

                    this.DBQuery(new DB_UpdateCharacter(this, bOnlyCharacter));

                    for(i = 0; i < 6;++i)
                    {
                        Summon cs  = this.GetSummonAt(i);
                        if (cs != null)
                        {
                            if ((cs.m_StatusFlag & StatusFlags.NeedToUpdateState) == 0 && this.m_bIsLogin && bOnlyCharacter)
                            {
                                cs.DBQuery(new DB_UpdateSummon(cs, false));
                            }
                            else
                            {
                                cs.DBQuery(new DB_UpdateSummon(cs, true));
                                cs.m_StatusFlag &= ~StatusFlags.NeedToUpdateState;
                            }
                        }
                    }


                    if (!bOnlyCharacter)
                    {
                        PlayerSaveQuestFunctor fn1 = new PlayerSaveQuestFunctor(this);
                        this.m_QuestManager.DoEachActiveQuest(fn1);

                        foreach (Item item in this.m_Inventory.m_vList)
                        {
                            if (item.m_bIsNeedUpdateToDB || item.IsExpireItem())
                            {
                                item.DBQuery(new DB_UpdateItem(item));
                            }
                        }

                        foreach (Item item in this.m_Storage.m_vList)
                        {
                            if (item.m_bIsNeedUpdateToDB || item.IsExpireItem())
                            {
                                item.DBQuery(new DB_UpdateItem(item));
                            }
                        }
                        
                        PlayerSaveSkillFunctor fn2 = new PlayerSaveSkillFunctor(this, this.m_bIsLogin == false);

                        this.EnumActiveSkill(fn2);

                        foreach (Summon sm in this.m_vSummonList)
                        {
                            sm.EnumActiveSkill(fn2);
                        }

                        foreach (Summon sm in this.m_vStorageSummonList)
                        {
                            sm.EnumActiveSkill(fn2);
                        }
                    }
                }
            }
        }

        public override void OnUpdate()
        {
            uint ct = Globals.GetArTime();

            this.m_bIsGaiaMember = false;
            if (this.m_nGaiaValidTime > ct)
                this.m_bIsGaiaMember = true;

            if (this.m_nChatPenalty > 0 && this.m_nNextChatPenaltyDecreaseTime < ct)
            {
                this.m_nChatPenalty -= 1;
                this.m_nNextChatPenaltyDecreaseTime += 3000;
            }

            if (this.m_nLastStaminaUpdateTime + 6000 < ct)
            {
                uint lst = (ct - this.m_nLastStaminaUpdateTime) / 0x1770;
                this.m_nLastStaminaUpdateTime += 6000 * lst;
                this.AddStamina((int)(this.GetStaminaRegenRate() * lst));
            }
            if (this.m_nLastBindSummonUpdateTime + 1000 < ct)
            {
                this.m_nLastBindSummonUpdateTime = ct;
                int psl = this.GetCurrentPassiveSkillLevel(1801);
                if (psl > 6 )
                    psl = 6;
                if (psl > 0 )
                {
                    for(int i = psl-1; i >= 0; --i)
                    {
                        if (this.m_aBindSummonCard[i] != null)
                        {
                            Summon s = this.m_aBindSummonCard[i].m_pSummon;

                            if (s != null)
                            {
                                if (!s.bIsInWorld)
                                    s.OnUpdate();
                            }
                        }
                    }
                }
            }
            if (this.m_nTmpJobId != this.GetJobId())
            {
                Messages.BroadcastPropertyMessage((uint)(this.mv.x / GameContent.g_nRegionSize), (uint)(this.mv.y / GameContent.g_nRegionSize), (sbyte)this.m_layer, this.m_hHandle, "job", this.m_nTmpJobId);
                Messages.SendJobInfo(this,this);
            }

            if (this.m_nTurnOffPkModeTime != 0 && this.m_nTurnOffPkModeTime < ct)
            {
                ServerLog.Log((ushort)0x904,this.m_nAccountID,this.GetSID(),0,0,0, (long) this.m_fImmoralPoint,0,0,0,0,0,this.m_szAccountName,this.GetName(),"","OFF");

                this.m_bIsPK = false;
                this.m_nTurnOffPkModeTime = 0;
                Messages.BroadcastStatusMessage(this);
            }

            if (this.m_nTurnOnPkModeTime != 0 && this.m_nTurnOnPkModeTime < ct)
            {
                float fIP = 5.0f;
                if (GameRule.bIsPKServer)
                    fIP = 0.0f;
                this.SetImmoralPoint(this.m_fImmoralPoint + fIP);
                ServerLog.Log((ushort)0x904, this.m_nAccountID, this.GetSID(), 0, 0, 0, (long)this.m_fImmoralPoint, 0, 0, 0, 0, 0, this.m_szAccountName, this.GetName(), "", "ON");
                this.m_bIsPK = true;
                this.m_nTurnOnPkModeTime = 0;
                Messages.BroadcastStatusMessage(this);
            }

            if (this.m_pSubSummon != null && this.m_nNextUnSummonTime < ct)
            {
                this.PendUnSummon(this.m_pSubSummon);
            }

            if (this.IsGameTimeLimited() && this.GetLastContinuousPlayTimeProcTime() + 3000 < ct)
            {
                this.SetContinuousPlayTime(ct - this.GetLastContinuousPlayTimeProcTime() + this.GetContinuousPlayTime());
                this.m_nLastContinuousPlayTimeProcTime = ct;
            }

            if (this.m_nLastSaveTime + 30000 < ct)
            {
                this.Save(false);
                ArPosition pos = this.GetCurrentPosition(ct);
                this.ChangeLocation(pos.x, pos.y, false, true);
            }
            if (this.m_nLastUpdateTime + 100 < ct)
            {
                if (this.ClearExpiredElementalEffect() || this.ClearExpiredItem())
                    this.CalculateStat();
            }
            if (GameRule.bUsePlayPoint)
            {
//                 v33 = v1->m_nPlayTime;
//                 LODWORD(nPlayTimeInMin) = (ct - v1->m_nLastPlayTimeUpdateTime) / 0x1770;
//                 LODWORD(fIP) = LODWORD(nPlayTimeInMin) + v33;
//                 v34 = GameRule::nPlayPointAccumulateAmount
//                     * ((LODWORD(nPlayTimeInMin) + v33) / GameRule::nPlayPointAccumulateTerm
//                      - v33 / GameRule::nPlayPointAccumulateTerm);
//                 nAccumulatedPlayTime = v34;
//                 if ( v34 )
//                 {
//                     if ( StructPlayer::GetPCBangMode(v1) == 2 )
//                         v34 = (nAccumulatedPlayTime * GameRule::fPremiumPCBangPlayPointBonusRate);
//                     v35 = GameDBManager::DBProc::operator new(0x16Cu);
//                     nAccumulatedPlayTime = v35;
//                     v58 = 0;
//                     if ( v35 )
//                         DB_UpdatePlayTimePoint::DB_UpdatePlayTimePoint(v35, v1, SLODWORD(nPlayTimeInMin), v34);
//                     else
//                         v36 = 0;
//                     StructPlayer::DBQuery(v1, v36);
//                     v1->m_nPlayTime = LODWORD(fIP);
//                     *&szString._Bx._Buf[8] = 0;
//                     v1->m_nLastPlayTimeUpdateTime = t;
//                     szString._Myres = 15;
//                     std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Eos(&szString, *&szString._Bx._Buf[8]);
//                     *&szString._Bx._Buf[8] = v34;
//                     v58 = 1;
//                     XStringUtil::Format(&szString, "@441\v#@point@#\v%d");
//                     v37 = *&szString._Bx._Buf[0];
//                     if ( szString._Myres < 0x10 )
//                         v37 = &szString._Bx;
//                     Messages.SendChatMessage(0, 20, "@NOTICE", v1, v37, 0);
//                     v58 = -1;
//                     std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&szString, 1, 0);
//                 }
            }
            if (this.m_nPartyId != 0)
                Messages.SendPartyPosition(this);

            processHotspots(ct);
            base.OnUpdate();
        }
// Function       :   public unsigned int GetTarget()

        public void SetTarget(uint target)
        {
            this.m_hTarget = target;
        }

// UserDefinedType:   SKILL_FUNCTOR
// VTable         :     , Type:  *
// Function       :     public void onSkill(const struct StructSkill *)
// Function       :     public void SKILL_FUNCTOR(const struct StructPlayer::SKILL_FUNCTOR &)
// Function       :     public void SKILL_FUNCTOR()
// Function       :     public struct StructPlayer::SKILL_FUNCTOR & operator=(const struct StructPlayer::SKILL_FUNCTOR &)
// Function       :   public void StructPlayer::EnumSummonPassiveSkill(struct StructPlayer::SKILL_FUNCTOR &)
// Function       :   public void StructPlayer::EnumSummonAmplifyPassiveSkill(struct StructPlayer::SKILL_FUNCTOR &)
// Function       :   public bool StructPlayer::CanLogoutNow()

        public override CreatureStat GetBaseStat()
        {
            int stat_id = 0;
            JobInfo job = GameContent.GetJobInfo(this.GetJobId());
            if (job != null )
                stat_id = job.stat_id;
            return GameContent.GetStatInfo(stat_id);
        }
// Function       :   public int GetPermission()

        public bool IsChatBlock()
        {
            return Globals.GetArTime() / 100 < this.m_nChatBlockTime;
        }

        public int GetChatBlockTime()
        {
            uint res = (uint)(this.m_nChatBlockTime - (Globals.GetArTime() / 100));
            if ((res & 0x80000000) == 0 )
                return (int)res;
            return 0;
        }
// Function       :   public int GetAdvChatCount()
// Function       :   public void StructPlayer::SetChatBlockTime(int)
        public override string GetName()
        {
            return m_szName;
        }

        public override int GetCreatureGroup()
        {
            return 9;
        }
// Function       :   public bool StructPlayer::ChangeName(const char *, const bool, const bool, const unsigned int)
        public string Name
        {
            get { return m_szName; }
            set { m_szName = value; }
        }
// Function       :   public void StructPlayer::OnChangeName(const char *, const bool, const bool, const bool)

        public override byte GetRace()
        {
            return (byte)m_nRace;
        }
// Function       :   public int GetSex()
// Function       :   public void StructPlayer::SetCreatureSpeed(unsigned char)
// Function       :   public void SetWalk(bool)
// Function       :   public bool IsWalking()

        public override void AddExp(long exp, long jp, bool bApplyStamina)
        {
            ArPosition pos;                         // -44 -2Ch
            long nSummonStaminaSaveBonusEXP = 0;        //  16  10h
            long nActivateSummonExp;                //  24  18h
            List<Summon> vActiveSummonList = new List<Summon>();         // 48, 30
            List<Summon> vDeActiveSummonList = new List<Summon>();       // 32, 20
            long nDeActiveSummonEXP;                //  64  40h
            long nGainExp;                          //  72  48h
            long gain_exp;                          //  84  54h
            long bonus_exp;                         //  92  5Ch
            long bonus_jp;
            bool bBonusSupplied;//  = byte ptr  78h
            int i;
// 
// Data           :   ebp Relative, [00000050], Local, Type: unsigned long, t
// Data           :   ebp Relative, [0000005C], Local, Type: class std::_Vector_iterator<StructSummon *,std::allocator<StructSummon *> >, it
// Data           :   ebp Relative, [00000048], Local, Type: class c_fixed<10000>, fGameTimeLimitPenalty
// Data           :   ebp Relative, [00000078], Local, Type: float, stamina_ratio
// Data           :   ebp Relative, [00000078], Local, Type: struct StructSummon *, pSummon
// Data           :   ebp Relative, [00000018], Local, Type: __int64, nActivateSummonExp
// Data           :   ebp Relative, [0000007B], Local, Type: bool, bBonusSupplied





            if (this.m_fImmoralPoint > GameRule.fCrimeLimit)
            {
                exp -= (long)((float)exp * 0.90f);
            }
            else if (this.m_fImmoralPoint > GameRule.fMoralLimit)
            {
                exp -= (long)((float)exp * (this.m_fImmoralPoint / 100.0f) * (float)exp * 0.09f);
            }

            Summon sm = this.m_pMainSummon;
            Summon subsm = this.m_pSubSummon;
            if (sm != null && sm.GetLevel() > this.GetLevel() || (subsm != null && subsm.GetLevel() > this.GetLevel()))
            {
                exp = Math.Min(exp, GameRule.GetPlayerEXPLimit(this.GetLevel()));
            }

            gain_exp = exp;
            if (this.IsGameTimeLimited())
            {
                float penalty = GameRule.GetGameTimeLimitPenalty(this.GetContinuousPlayTime());
                exp = (int)(penalty * (float)exp);
                jp = (int)(penalty * (float)jp);
            }

            if (exp != 0)
            {
                if (this.m_eSummonStaminaSaveType != SummonStaminSaverType.SummonStaminaSaverNone)
                    nSummonStaminaSaveBonusEXP = (long)((float)exp * GameRule.fSummonStatminaSaveBonusRate);
                else
                    nSummonStaminaSaveBonusEXP = 0;

                // this section should be first since we are ditching the playing time BS
                /////////////////
                if (bApplyStamina)
                {
                    gain_exp = (long)((float)gain_exp / GameRule.GetStaminaRatio(this.GetLevel()));
                    if (this.m_nStamina >= gain_exp || this.m_bStaminaSave)
                    {
                        bonus_exp = (long)((double)exp * GameRule.fStaminaBonusRate);
                        bonus_jp = (int)((double)jp * GameRule.fStaminaBonusRate);
                        if (bonus_exp != 0 || bonus_jp != 0)
                        {
                            this.setBonusMsg(BonusType.Stamina, (int)(GameRule.fStaminaBonusRate * 100.0f), bonus_exp, (int)bonus_jp);
                            exp += bonus_exp;
                            jp += (int)bonus_jp;
                        }
                        if (!this.m_bStaminaSave)
                            this.AddStamina((int)(0 - gain_exp));
                    }
                }

                // Build our different summon lists

                uint ct = Globals.GetArTime();

                pos = this.GetCurrentPosition(ct);

                for (i = 0; i < 6; ++i)
                {
                    Summon summon1 = this.GetSummonAt(i);

                    if (summon1 != null && summon1.m_nHP != 0 && summon1.GetRidingInfo() != 1)
                    {
                        if (!summon1.bIsInWorld)
                        {
                            vDeActiveSummonList.Add(summon1);
                        }
                        else 
                        {
                            ArPosition posSummon = summon1.GetCurrentPosition(ct);
                            if (pos.GetDistance(posSummon) <= 525.0f)
                            {
                                vActiveSummonList.Add(summon1);
                            }
                        }
                    }
                }

                // do our vActiveSummonList array
                nActivateSummonExp = GameRule.GetIntValueByRandomInt64((this.m_fActiveSummonExpAmp + this.m_fDistEXPMod) * (double)exp);
                bBonusSupplied = false;

                foreach (Summon sum1 in vActiveSummonList)
                {
                    if (!sum1.IsEXPLimitReached())
                    {
                        if (sum1.GetLevel() >= this.GetLevel())
                        {
                            nGainExp = 0;
                        }
                        else
                        {
                            nGainExp = nActivateSummonExp;
                        }

                        if (this.m_eSummonStaminaSaveType == SummonStaminSaverType.SummonStaminaSaverWithoutPenalty
                          || this.m_eSummonStaminaSaveType == SummonStaminSaverType.SummonStaminaSaverWithPenalty
                          && sum1.GetLevel() < this.GetLevel())
                        {
                            nGainExp += (nSummonStaminaSaveBonusEXP + nActivateSummonExp);
                            bBonusSupplied = true;
                        }
                        if (nGainExp != 0)
                        {
                            sum1.AddExp(nGainExp, 0, true);
                        }
                    }
                }
                if (bBonusSupplied)
                {
                    this.setBonusMsg(BonusType.Stamina, (int)(GameRule.fSummonStatminaSaveBonusRate * 100.0f), nSummonStaminaSaveBonusEXP, 0);
                }

                ///// inactive list now
                nDeActiveSummonEXP = GameRule.GetIntValueByRandomInt64((this.m_fDistEXPMod - 1.0f + this.m_fDeactiveSummonExpAmp) * (double)exp);
                foreach (Summon sum2 in vDeActiveSummonList)
                {
                    if (sum2.GetLevel() >= this.GetLevel() || sum2.IsEXPLimitReached())
                        nDeActiveSummonEXP = 0;

                    sum2.AddExp(nDeActiveSummonEXP, 0, true);
                }

                /// end of nEXP test
                /////
                if (GameRule.nMaxLevel > 0)
                {
                    long maxExp = GameContent.GetNeedExp(GameRule.nMaxLevel - 1);
                    if (this.m_nEXP > maxExp)
                    {
                        exp = maxExp - this.m_nEXP;
                    }
                }
                if (jp > 0)
                {
                    if (this.m_nJobPoint < Constants.MAX_JP)
                    {
                        if (Constants.MAX_JP - this.m_nJobPoint < jp)
                            jp = Constants.MAX_JP - this.m_nJobPoint;
                    }
                    else
                    {
                        jp = 0;
                        Messages.SendChatMessage(false, 30, "@SYSTEM", this, "@6759", 0);
                    }
                }
                base.AddExp(exp, jp, true);
            }
        }


// Function       :   public __int64 StructPlayer::GetDeadEXPPenalty()

        public bool IsHunter()
        {
            int job_id = this.GetJobId();
            if (job_id == 0)
            {
                switch(m_nRace)
                {
                    case 3:
                        job_id = 100;
                        break;
                    case 4:
                        job_id = 200;
                        break;
                    case 5:
                        job_id = 300;
                        break;
                }
            }
            JobInfo info = GameContent.GetJobInfo(job_id);

            if (info != null)
                return info.job_class == 2;
            return false;
        }

        public bool IsFighter()
        {
            int job_id = this.GetJobId();
            if (job_id == 0)
            {
                switch (m_nRace)
                {
                    case 3:
                        job_id = 100;
                        break;
                    case 4:
                        job_id = 200;
                        break;
                    case 5:
                        job_id = 300;
                        break;
                }
            }
            JobInfo info = GameContent.GetJobInfo(job_id);

            if (info != null)
                return info.job_class == 1;
            return false;
        }

        public bool IsMagician()
        {
            int job_id = this.GetJobId();
            if (job_id == 0)
            {
                switch (m_nRace)
                {
                    case 3:
                        job_id = 100;
                        break;
                    case 4:
                        job_id = 200;
                        break;
                    case 5:
                        job_id = 300;
                        break;
                }
            }
            JobInfo info = GameContent.GetJobInfo(job_id);

            if (info != null)
                return info.job_class == 3;
            return false;
        }

        public bool IsSummoner()
        {
            int job_id = this.GetJobId();
            if (job_id == 0)
            {
                switch (m_nRace)
                {
                    case 3:
                        job_id = 100;
                        break;
                    case 4:
                        job_id = 200;
                        break;
                    case 5:
                        job_id = 300;
                        break;
                }
            }
            JobInfo info = GameContent.GetJobInfo(job_id);

            if (info != null)
                return info.job_class == 4;
            return false;
        }
// Function       :   public bool StructPlayer::ResetJob(const int)
// Function       :   public int GetCharisma()
// Function       :   public int StructPlayer::GetMoveSpeed()
// Function       :   public int GetMaxChaos()
// Function       :   public int GetChaos()

        public void AddChaos(int nChaos)
        {
            this.m_nChaos += nChaos;
            if (this.m_nChaos > this.m_nMaxChaos)
                this.m_nChaos = this.m_nMaxChaos;
            if (this.m_nChaos < 0 )
                this.m_nChaos = 0;
            this.m_QuestManager.UpdateQuestStatusByParameter(99, this.m_nChaos);
            Messages.SendPropertyMessage(this, this.m_hHandle, "chaos", (long)this.m_nChaos);
        }

        public bool StartQuest(int code, int nStartQuestID, bool bForce)
        {
            bool bHasRandomQuest;
            string buf;

            RLock rl = RappelzServer.Instance._LockObject(this);
            AutoLock al = new AutoLock(rl.handle);

            QuestBaseServer rQuestBase = Quest.GetQuestBase(code);
            if (this.IsGameTimeLimited())
            {
                if (this.GetContinuousPlayTime() >= GameRule.nMaxTiredGameTime)
                {
                    buf = String.Format("START|FAIL|GAME_TIME_LIMIT|{0}", rQuestBase.nQuestTextId);
                    Messages.SendQuestMessage(120, this, buf);
                    //ArcadiaAutoLock::_ArcadiaAutoLock(&_lock);
                    return false;
                }
                if (this.GetContinuousPlayTime() >= GameRule.nMaxHealthyGameTime)
                {
                    buf = String.Format("START|WARNING|GAME_TIME_LIMIT|{0}", rQuestBase.nQuestTextId);
                    Messages.SendQuestMessage(120, this, buf);
                }
            }
            if (this.m_QuestManager.m_vActiveQuest.Count >= 20)
            {
                buf = String.Format("START|FAIL|QUEST_NUMBER_EXCEED|{0}", rQuestBase.nQuestTextId);
                Messages.SendQuestMessage(120, this, buf);
                return false;
            }
            if (!bForce && !this.IsStartableQuest(code, false))
            {
                buf = String.Format("START|FAIL|NOT_STARTABLE|{0}", rQuestBase.nQuestTextId);
                Messages.SendQuestMessage(120, this, buf);
                return false;
            }
            bHasRandomQuest = false;
            if (Quest.IsRandomQuest(code) && this.m_QuestManager.HasRandomQuestInfo(code))
                bHasRandomQuest = true;
            if (this.m_QuestManager.StartQuest(code, nStartQuestID))
            {
                Quest q = this.m_QuestManager.FindQuest(code);
                if (q == null)
                {
//                    ArcadiaAutoLock::_ArcadiaAutoLock(&_lock);
                    return false;
                }

                this.m_nLastAcceptQuest = code;
                this.onStartQuest(q);

                this.DBQuery(new DB_InsertQuest(this,this.m_nUID,q.m_Instance.nId,q.m_Instance.Code, q.m_Instance.nTime, q.m_Instance.nStartID,q.GetStatus(0),
                    q.GetStatus(1),q.GetStatus(2),q.GetStatus(3),q.GetStatus(4),q.GetStatus(5),(int)q.m_Instance.nProgress));

                if (!Quest.IsRandomQuest(q.m_Instance.Code))
                {
//        LABEL_31:
                    buf = String.Format("START|SUCCESS|{0}", rQuestBase.nCode);
                    Messages.SendQuestMessage(120, this, buf);
                    Messages.SendQuestList(this);
                    if (q.m_QuestBase.strAcceptScript.Length > 0)
                    {
                        LuaVM.Instance.RunString(this,q.m_QuestBase.strAcceptScript);
                    }

                    ServerLog.Log((ushort)0xAF1u,this.m_nAccountID,this.GetSID(),0,q.m_Instance.Code,q.m_Instance.nId,0,0,0,0,0,0,this.m_szAccountName,
                        this.GetName(),GameContent.GetString(rQuestBase.nQuestTextId),"");

//                    ArcadiaAutoLock::_ArcadiaAutoLock(&_lock);
                    return true;
                }
                if (bHasRandomQuest)
                {
                    this.DBQuery(new DB_UpdateRandomQuest(this,this.m_nUID,q.m_Instance.Code,q.GetRandomKey(0),q.GetRandomKey(1),q.GetRandomKey(2),
                        q.GetRandomValue(0),q.GetRandomValue(1),q.GetRandomValue(2),0));
                    buf = String.Format("START|SUCCESS|{0}", rQuestBase.nCode);
                    Messages.SendQuestMessage(120, this, buf);
                    Messages.SendQuestList(this);
                    if (q.m_QuestBase.strAcceptScript.Length > 0)
                    {
                        LuaVM.Instance.RunString(this,q.m_QuestBase.strAcceptScript);
                    }

                    ServerLog.Log((ushort)0xAF1u,this.m_nAccountID,this.GetSID(),0,q.m_Instance.Code,q.m_Instance.nId,0,0,0,0,0,0,this.m_szAccountName,
                        this.GetName(),GameContent.GetString(rQuestBase.nQuestTextId),"");

//                    ArcadiaAutoLock::_ArcadiaAutoLock(&_lock);
                    return true;
                }
                else
                {
/*
                    HIDWORD(n9) = GameDBManager::DBProc::operator new(0x184u);
                    LOBYTE(v38) = 3;
                    if ( HIDWORD(n9) )
                    {
                        HIDWORD(n11) = v10->m_Instance.Code;
                        HIDWORD(n10) = v4->m_nUID;
                        *&buf[236] = StructQuest::GetRandomValue(v10, 2);
                        *&buf[232] = StructQuest::GetRandomValue(v10, 1);
                        *&buf[228] = StructQuest::GetRandomValue(v10, 0);
                        *&buf[224] = StructQuest::GetRandomKey(v10, 2);
                        *&buf[220] = StructQuest::GetRandomKey(v10, 1);
                        v14 = StructQuest::GetRandomKey(v10, 0);
                        DB_InsertRandomQuest::DB_InsertRandomQuest(
                            HIDWORD(n9),
                            v4,
                            SHIDWORD(n10),
                            SHIDWORD(n11),
                            v14,
                            *&buf[220],
                            *&buf[224],
                            *&buf[228],
                            *&buf[232],
                            *&buf[236]);
                        LOBYTE(v38) = 0;
                        StructPlayer::DBQuery(v4, v14);
                        buf = String.Format("START|SUCCESS|{0}", rQuestBase.nCode);
                        Messages.SendQuestMessage(120, this, buf);
                        Messages.SendQuestList(this);
                        if (q.m_QuestBase.strAcceptScript.Length > 0)
                        {
                            LuaVM.Instance.RunLuaScript(q.m_QuestBase.strAcceptScript);
                        }

                        ServerLog.Log((ushort)0xAF1u,this.m_nAccountID,this.GetSID(),0,q.m_Instance.Code,q.m_Instance.nId,0,0,0,0,0,0,this.m_szAccountName,
                            this.GetName(),GameContent.GetString(rQuestBase.nQuestTextId),"");

    //                    ArcadiaAutoLock::_ArcadiaAutoLock(&_lock);
                        return true;
                    }
*/
                }
//                v14 = 0;
//                goto LABEL_30;
            }
            buf = String.Format("START|FAIL|NOT_STARTABLE|{0}", rQuestBase.nQuestTextId);
            Messages.SendQuestMessage(120, this, buf);
//         LABEL_18:
//             v38 = -1;
//            ArcadiaAutoLock::_ArcadiaAutoLock(&_lock);
            return false;
        }

        public void UpdateQuestByQuestEnd(Quest pQuest)
        {
//             if (pQuest.m_QuestBase.nIsMagicPointQuest != 0)
//             {
//                 int points = Marshal.ToInt32(this.GetFlag("mc_points"), 0);
//                 points += 2;
//                 this.SetFlag("mc_points", points.ToString());
//                 Quest q = this.m_QuestManager.FindQuest(3281);
//                 if(q != null)
//                     q.UpdateStatus(0, points);
//                 q = this.m_QuestManager.FindQuest(3282);
//                 if (q != null)
//                     q.UpdateStatus(0, points);
//                 q = this.m_QuestManager.FindQuest(3283);
//                 if (q != null)
//                     q.UpdateStatus(0, points);
//                 q = this.m_QuestManager.FindQuest(3284);
//                 if (q != null)
//                     q.UpdateStatus(0, points);
// 
//             }

        }


        public bool EndQuest(int code, int nSelectRewardIdx, bool bForce)
        {
// .text:0045D0F7 var_90          = qword ptr -90h
// .text:0045D0F7 anonymous_0     = qword ptr -88h
// .text:0045D0F7 var_80          = qword ptr -80h
// .text:0045D0F7 _lock           = ArcadiaAutoLock ptr -44h
// .text:0045D0F7 code            = dword ptr  4
            float fMod;                         //  36   24h
// .text:0045D0F7 fRewardRate     = c_fixed<10000> ptr  40h
            int nMaxItemCollectTypeCount;       //  76   4Ch
// .text:0045D0F7 nRewardGold     = StructGold ptr  50h
// .text:0045D0F7 nQuantity       = qword ptr  58h
// .text:0045D0F7 pNewItem        = dword ptr  60h
// .text:0045D0F7 it              = StructCreature::iterator ptr  64h
// .text:0045D0F7 pItem           = dword ptr  74h
// .text:0045D0F7 nSelectRewardIdx= dword ptr  78h
            Quest pQuest = null;                       //  96   60h
            Item pItem = null;
            long nPrevGold = 0;
            long nRewardJP = 0;
            long nRewardExp = 0;
            int favor_id;
            int hate_id;
            int nItemCode;
            int i;

// Data           :   ebp Relative, [00000074], Local, Type: int, favor_id
// Data           :   ebp Relative, [00000050], Local, Type: struct StructGold, nRewardGold
// Data           :   ebp Relative, [00000064], Local, Type: __int64, nRewardExp
// Data           :   ebp Relative, [00000064], Local, Type: struct StructGold, nPrevGold
// Data           :   ebp Relative, [FFFFFFBC], Local, Type: struct ArcadiaAutoLock, _lock
// Data           :   ebp Relative, [00000074], Local, Type: int, hate_id
// Data           :   ebp Relative, [00000040], Local, Type: class c_fixed<10000>, fRewardRate
// Data           :   ebp Relative, [00000074], Local, Type: int, i
// Data           :   ebp Relative, [00000074], Local, Type: int, nRewardJP
// Data           :   ebp Relative, [00000024], Local, Type: float, fMod
// Data           :   ebp Relative, [00000060], Local, Type: int, i
// Data           :   ebp Relative, [00000058], Local, Type: __int64, nMaxEXP
// Data           :   ebp Relative, [00000064], Local, Type: struct StructCreature::iterator, it
// Data           :   ebp Relative, [00000064], Local, Type: struct StructCreature::iterator, it
// Data           :   ebp Relative, [0000004C], Local, Type: int, nMaxItemCollectTypeCount
// Data           :   ebp Relative, [00000060], Local, Type: int, nItemCode
// Data           :   ebp Relative, [00000058], Local, Type: __int64, nQuantity
// Data           :   ebp Relative, [00000060], Local, Type: struct StructItem *, pNewItem
// Data           :   ebp Relative, [00000074], Local, Type: struct StructItem *, pItem
// Data           :   ebp Relative, [00000078], Local, Type: struct StructItem *, pNewItem
// Data           :   ebp Relative, [00000074], Local, Type: struct StructItem *, pItem
            RLock rl;
            AutoLock al;


            rl = RappelzServer.Instance._LockObjectWithVisibleRange(this);
            al = new AutoLock(rl.handle);

            if ( !this.CheckFinishableQuestAndGetQuestStruct(code, out pQuest, bForce))
            {
                Messages.SendQuestMessage(120, this, "END|FAIL|0");
//                ArcadiaAutoLock::_ArcadiaAutoLock((v3 - 68));
                return false;
            }
            nPrevGold = this.m_nGold;
            fMod = 0.0f;
            if (Quest.IsRandomQuest(pQuest.m_Instance.Code))
            {
                i = 0;
                nMaxItemCollectTypeCount = 3;
                do
                {
                    fMod += (float)(pQuest.GetRandomValue(i++) * pQuest.GetValue(nMaxItemCollectTypeCount)) / 100.0f;
                    nMaxItemCollectTypeCount += 4;
                }
                while (nMaxItemCollectTypeCount <= 15);
            }
            else
            {
                fMod = 1.0f;
            }

            ushort res = this.ChangeGold((long)((double)pQuest.m_QuestBase.nGold * (double)fMod)+this.m_nGold);
            if (res != 0)
            {
                Messages.SendQuestMessage(120, this, "END|TOO_MUCH_MONEY|%d", res);
//                ArcadiaAutoLock::_ArcadiaAutoLock((v3 - 68));
                return false;

            }
            if (this.m_QuestManager.EndQuest(pQuest))
            {
                Messages.SendQuestMessage(120, this,
                    "END|EXP|{0}|{1}|{2}|{3}|{4}",pQuest.m_Instance.Code,pQuest.m_QuestBase.nExp,pQuest.m_QuestBase.nJP,pQuest.m_QuestBase.nGold,
                    pQuest.m_QuestBase.nHuntaholicPoint);

                nRewardExp = pQuest.m_QuestBase.nExp;
                if (GameRule.nMaxLevel > 0)
                {
                    if (pQuest.m_QuestBase.nExp + this.m_nEXP >= GameContent.GetNeedExp(GameRule.nMaxLevel - 1))
                    {
                        if (this.m_nEXP < GameContent.GetNeedExp(GameRule.nMaxLevel - 1))
                        {
                            nRewardExp = GameContent.GetNeedExp(GameRule.nMaxLevel - 1) - this.m_nEXP;
                        }
                        else
                        {
                            nRewardExp = 0;
                        }
                    }
                }

                nRewardJP = (int)((float)pQuest.m_QuestBase.nJP * fMod);

                if (nRewardJP > 0)
                {
                    if (this.m_nJobPoint < Constants.MAX_JP)
                    {
                        if (Constants.MAX_JP - this.m_nJobPoint < nRewardJP)
                            nRewardJP = Constants.MAX_JP - this.m_nJobPoint;
                    }
                    else
                    {
                        nRewardJP = 0;
                        Messages.SendChatMessage(false, 30, "@SYSTEM", this, "@6759", 0);
                    }
                }

                this.AddExp((long)((double)nRewardExp * (double)fMod), nRewardJP, false);

                int huntPt = (int)((float)pQuest.m_QuestBase.nHuntaholicPoint*fMod);
                if (huntPt >= 1)
                    this.SetHuntaholicPoint(this.GetHuntaholicPoint() + huntPt);

                favor_id = pQuest.m_QuestBase.nFavorGroupId;
                if (favor_id == 999 )
                {
                    NPC npc = Creature.get(this.GetLastContactLong("npc")) as NPC;

                    if (npc != null && npc.IsNPC())
                        favor_id = npc.m_BaseInfo.id;
                    else
                        favor_id = 0;
                }

                if (favor_id != 0)
                    this.AddFavor(favor_id, (int)((float)pQuest.m_QuestBase.nFavor * fMod));

                hate_id = pQuest.m_QuestBase.nHateGroupId;
                if (hate_id == 999 )
                {
                    NPC npc = Creature.get(this.GetLastContactLong("npc")) as NPC;
                    
                    if (npc != null && npc.IsNPC())
                        hate_id = npc.m_BaseInfo.id;
                    else
                        hate_id = 0;
                }
                if (hate_id != 0)
                    this.AddFavor(hate_id, 0-(int)((float)pQuest.m_QuestBase.nFavor * fMod));

                if (pQuest.m_QuestBase.nType == QuestBase.QuestType.Collect || pQuest.m_QuestBase.nType == QuestBase.QuestType.HuntItem || pQuest.m_QuestBase.nType == QuestBase.QuestType.HuntItemFromAnyMonsters)
                {
                    for(i = 0; i < ((pQuest.m_QuestBase.nType == QuestBase.QuestType.Collect) ? 6 : 3);++i)
                    {
                        nItemCode = pQuest.GetValue(2 * i);
                        if (nItemCode != 0)
                        {
                            pItem = this.m_Inventory.FindByCode(nItemCode);
                            if (pItem != null)
                                this.EraseItem(pItem, pQuest.GetValue((2 * i) + 1));
                        }
                    }
                }

                if (pQuest.m_QuestBase.DefaultReward.nItemCode != 0)
                {
                    pItem = Item.AllocItem(0,pQuest.m_QuestBase.DefaultReward.nItemCode,(long)((float)pQuest.m_QuestBase.DefaultReward.nQuantity * fMod), 
                        ItemInstance.GenerateCode.ByQuest,pQuest.m_QuestBase.DefaultReward.nLevel < 1 ? 1 : pQuest.m_QuestBase.DefaultReward.nLevel,-1,-1,-1,0,0,0,0,
                        -1,0,0,0,0);
                    Item pItem2 = this.PushItem(pItem, pItem.m_Instance.nCount, false);

                    if (pItem2 != null)
                    {
                        ServerLog.Log((ushort)0x961,this.m_nAccountID,this.GetSID(),pItem.m_Instance.nLevel + 100 * pItem.m_Instance.nEnhance,
                            pItem2.m_Instance.Code,pItem.m_Instance.nCount,pItem2.m_Instance.nCount,pQuest.m_QuestBase.nGold,this.m_nGold,
                            (long)this.mv.x,(long)this.mv.y,pItem2.m_Instance.UID,this.m_szAccountName,this.GetName(),"","QUEST");
                    }
                    Messages.SendQuestMessage(120, this, "END|REWARD|{0}", pItem.m_Instance.Code);
                    if (!ReferenceEquals(pItem, pItem2))
                        Item.PendFreeItem(pItem);
                }
                if (nSelectRewardIdx >= 0 && nSelectRewardIdx < QuestBase.MAX_OPTIONAL_REWARD && pQuest.m_QuestBase.OptionalReward[nSelectRewardIdx].nItemCode != 0)
                {
                    QuestBase.Reward reward = pQuest.m_QuestBase.OptionalReward[nSelectRewardIdx];
                    pItem = Item.AllocItem(0,reward.nItemCode, (int)((float)reward.nQuantity*fMod),ItemInstance.GenerateCode.ByQuest,
                        reward.nLevel < 1 ? 1 : reward.nLevel,-1,-1,-1,0,0,0,0,-1,0,0,0,0);
                    Item pItem2 = this.PushItem(pItem, pItem.m_Instance.nCount,false);
                    if (pItem2 != null)
                    {
                        ServerLog.Log((ushort)0x961,this.m_nAccountID,this.GetSID(),pItem.m_Instance.nLevel + 100 * pItem.m_Instance.nEnhance,
                            pItem2.m_Instance.Code,pItem.m_Instance.nCount,pItem2.m_Instance.nCount,pQuest.m_QuestBase.nGold,this.m_nGold,
                            (long)this.mv.x,(long)this.mv.y,pItem2.m_Instance.UID,this.m_szAccountName,this.GetName(),"","QUEST");
                    }
                    Messages.SendQuestMessage(120, this, "END|REWARD|{0}", pItem.m_Instance.Code);
                    if (!ReferenceEquals(pItem, pItem2))
                        Item.PendFreeItem(pItem);
                }
                if (pQuest.m_QuestBase.nIsMagicPointQuest != 0)
                    UpdateQuestByQuestEnd(pQuest);

                this.DBQuery(new DB_UpdateQuest(this,this.m_nUID,pQuest.m_Instance.nId,pQuest.GetStatus(0),pQuest.GetStatus(1),pQuest.GetStatus(2),
                    pQuest.GetStatus(3),pQuest.GetStatus(4),pQuest.GetStatus(5),(int)pQuest.m_Instance.nProgress, pQuest.m_Instance.nTime));
                
                ServerLog.Log((ushort)0xAF3, this.m_nAccountID,this.GetSID(),0,pQuest.m_Instance.Code,pQuest.m_Instance.nId,0,0,0,0,0,0,
                    this.m_szAccountName,this.GetName(),GameContent.GetString(pQuest.m_QuestBase.nQuestTextId),"");
                this.onEndQuest(pQuest);
                Messages.SendQuestList(this);
                if (!String.IsNullOrEmpty(pQuest.m_QuestBase.strClearScript))
                {
                    LuaVM.Instance.RunString(this, pQuest.m_QuestBase.strClearScript);
                }
                this.Save(false);
                //            ArcadiaAutoLock::_ArcadiaAutoLock((v3 - 68));
                return true;
            }
            else
            {
                if (this.ChangeGold(nPrevGold) != 0)
                {
                    Globals.Log.Error("ChangeGold/ChangeStorageGold Failed: Case[6], Player[{0}], Info[Owned({1}), Target({2})]",
                        this.GetName(),this.m_nGold,nPrevGold);
                }
                Messages.SendQuestMessage(120, this, "END|FAIL|0");
            }
//            ArcadiaAutoLock::_ArcadiaAutoLock((v3 - 68));
            return false;
        }

        public bool DropQuest(int code)
        {
            RLock rl = RappelzServer.Instance._LockObject(this);
            AutoLock al = new AutoLock(rl.handle);

            Quest q = this.m_QuestManager.FindQuest(code);
            if (q == null)
                return false;

            this.DBQuery(new DB_DeleteQuest(this, this.m_nUID, q.m_Instance.nId));

            if (Quest.IsRandomQuest(q.m_Instance.Code) )
            {
                this.DBQuery(new DB_UpdateRandomQuest(this, this.m_nUID, q.m_Instance.nId,q.GetRandomKey(0),
                    q.GetRandomKey(1),q.GetRandomKey(2),q.GetRandomValue(0),q.GetRandomValue(1),q.GetRandomValue(2),1));

                this.m_QuestManager.SetDropFlagToRandomQuestInfo(q.m_Instance.Code);
            }

            ServerLog.Log((ushort)0xAF2,this.m_nAccountID,this.GetSID(),0,q.m_Instance.Code,q.m_Instance.nId,0,0,0,0,0,0,
                this.m_szAccountName,this.GetName(),GameContent.GetString(q.m_QuestBase.nQuestTextId),"");
            this.onDropQuest(q);
            Messages.SendQuestList(this);
//            ArcadiaAutoLock::_ArcadiaAutoLock((v2 - 124));
            return true;
        }

        public int GetQuestProgress(int code)
        {
            int result;

            if (this.m_QuestManager.IsStartableQuest(code))
            {
                result = 0;
            }
            else if (this.m_QuestManager.IsFinishedQuest(code))
            {
                result = 255;
            }
            else
            {
                Quest q = this.m_QuestManager.FindQuest(code);
                if (q != null)
                    result = q.IsFinishable() ? 2 : 1;
                else
                    result = -1;
            }

            return result;
        }

        public bool DoEachActiveQuest(QMQuestFunctor fn)
        {
            return true;
        }
// Function       :   public unsigned int GetActiveQuestCount()
// Function       :   public int GetLastAcceptQuest()

        public bool IsStartableQuest(int code, bool bForQuestMark)
        {
            QuestBaseServer qbs = Quest.GetQuestBase(code);
            if (qbs.nLimitLevel - this.GetLevel() > 4
              || qbs.nLimitJobLevel > this.GetJobLevel()
              || bForQuestMark
              && qbs.nLimitIndication != 0
              && this.GetLevel() - qbs.nLimitLevel > 12 )
                return false;
            
            if (qbs.nLimitJob != 0)
            {
                if (qbs.nLimitJob != this.GetJobId())
                    return false;
            }
            else
            {
                if ( (!this.IsHunter() || (qbs.LimitFlag & 0x20) == 0)
                  && (!this.IsFighter() || (qbs.LimitFlag & 0x10) == 0)
                  && (!this.IsMagician() || (qbs.LimitFlag & 0x40) == 0)
                  && (!this.IsSummoner() || (qbs.LimitFlag & 0x80) == 0))
                    return false;
            }
            if ( (this.GetRace() != 3 || (qbs.LimitFlag & 8) == 0)
              && (this.GetRace() != 4 || (qbs.LimitFlag & 2) == 0)
              && (this.GetRace() != 5 || (qbs.LimitFlag & 4) == 0))
                return false;
            int fgid = qbs.nLimitFavorGroupId;
            if (fgid == 999 )
            {
                NPC npc = Creature.get((uint)this.GetLastContactLong("npc")) as NPC;

                if (npc != null)
                    fgid = npc.m_BaseInfo.id;
                else
                    fgid = 0;
            }
            if (fgid != 0 && this.GetFavor(fgid) < qbs.nLimitFavor)
                return false;
            return this.m_QuestManager.IsStartableQuest(code);

        }

        public bool IsInProgressQuest(int code)
        {
            bool result;

            Quest q = this.m_QuestManager.FindQuest(code);
            if (q != null)
                result = !q.IsFinishable();
            else
                result = false;
            return result;
        }

        public bool IsFinishableQuest(int code)
        {
            return this.CheckFinishableQuestAndGetQuestStruct(code);
        }

        public bool IsTakeableQuestItem(int code)
        {
            return this.m_QuestManager.IsTakeableQuestItem(code);
        }        

        public bool CheckFinishableQuestAndGetQuestStruct(int code, out Quest pQuest, bool bForce)
        {
            bool result;

            Quest q1 = this.m_QuestManager.FindQuest(code);

            if (q1 != null && (q1.IsFinishable() || bForce))
            {
                pQuest = q1;
                result = true;
            }
            else
            {
                pQuest = null;
                result = false;
            }
            return result;
        }

        public bool CheckFinishableQuestAndGetQuestStruct(int code)
        {
            bool result;

            Quest q1 = this.m_QuestManager.FindQuest(code);

            if (q1 != null && q1.IsFinishable())
            {
                result = true;
            }
            else
            {
                result = false;
            }
            return result;
        }

        public Quest FindQuest(int code)
        {
            return this.m_QuestManager.FindQuest(code);
        }

        public void GetQuestByMonster(int nMonsterId, List<Quest> vQuest, int type)
        {
            this.m_QuestManager.GetRelatedQuestByMonster(nMonsterId, vQuest, type);
        }

        public void UpdateQuestStatusByMonsterKill(int nMonsterId)
        {
            this.m_QuestManager.UpdateQuestStatusByMonsterKill(nMonsterId);
        }

// Function       :   public const struct StructGold GetGold()
// Function       :   public const struct StructGold GetStorageGold()

        public ushort ChangeStorageGold(long gold)
        {
            if (this.m_nStorageGold != gold)
            {
                if (gold > Constants.MAX_GOLD_FOR_STORAGE)
                    return 53;
                if (gold < 0)
                    return 50;
                this.m_nStorageGold = gold;
                this.DBQuery(new DB_UpdateStorageGold(this));
                Messages.SendPropertyMessage(this, this.m_hHandle, "storage_gold", this.m_nStorageGold);
            }
            return 0;
        }
        public ushort ChangeGold(long gold)
        {
            if (gold != m_nGold)
            {
                if (gold > Constants.MAX_GOLD_FOR_INVENTORY)
                    return 53;
                if (gold < 0)
                    return 50;
                this.m_nGold = gold;
                Messages.SendGoldChaosUpdateMsg(this);
            }
            return 0;
        }
// Function       :   public int GetBaseModelId(int)
// Function       :   public const char * StructPlayer::GetClientInfo()
        public override bool IsUsingBow()
        {
            bool result = false;

            Item pWeapon = this.m_anWear[0];
            if (pWeapon != null)
                result = pWeapon.IsBow();
            return result;
        }

        public override bool IsUsingCrossBow()
        {
            bool result = false;

            Item pWeapon = this.m_anWear[0];
            if (pWeapon != null)
                result = pWeapon.IsCrossBow();
            return result;
        }

        public override bool TranslateWearPosition(ref ItemBase.ItemWearType pos, Item pItem, ref List<int> vpOverlappItemList)
        {
//.text:0045732A var_28          = dword ptr -28h
            float current_bag_capacity;                     // -24  -18h
            float new_bag_capacity;                         // -16  -10h
            int nCurrentVarIdx;                             // -8   -8h
//.text:0045732A var_4           = dword ptr -4
//.text:0045732A pos             = dword ptr  8
//.text:0045732A pItem           = dword ptr  0Ch
//.text:0045732A vpOverlappItemList= dword ptr  10h
            Item item1;
            Item item2;
            int i;

            if (!base.TranslateWearPosition(ref pos, pItem, ref vpOverlappItemList))
                return false;
            if ((pItem.m_Instance.Flag & 1) != 0)
                return false;
            bool ok = false;
            if ((pItem.m_pItemBase.nLimit & (int)ItemBase.LimitFlag.Hunter) != 0 && this.IsHunter())
                ok = true;

            if ((pItem.m_pItemBase.nLimit & (int)ItemBase.LimitFlag.Fighter) != 0 && this.IsFighter())
                ok = true;

            if ((pItem.m_pItemBase.nLimit & (int)ItemBase.LimitFlag.Magician) != 0 && this.IsMagician())
                ok = true;

            if ((pItem.m_pItemBase.nLimit & (int)ItemBase.LimitFlag.Summoner) != 0 && this.IsSummoner())
                ok = true;

            if (!ok 
              || this.GetRace() == 3 && (pItem.m_pItemBase.nLimit & (int)ItemBase.LimitFlag.Gaia) == 0
              || this.GetRace() == 4 && (pItem.m_pItemBase.nLimit & (int)ItemBase.LimitFlag.Deva) == 0
              || this.GetRace() == 5 && (pItem.m_pItemBase.nLimit & (int)ItemBase.LimitFlag.Asura) == 0)
                return false;
            if (pos == ItemBase.ItemWearType.WearShield)
            {
                if (pItem.m_pItemBase.nGroup == (int)ItemBase.ItemGroup.Bullet)
                {
                    item1 = this.m_anWear[0];
                    if (item1 == null 
                        || item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassCrossBow 
                        && item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassLightBow
                        && item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassHeavyBow)
                        return false;
                }
                if (pItem.m_pItemBase.nGroup == (int)ItemBase.ItemGroup.Weapon)
                {
                    item1 = this.m_anWear[0];
                    if (item1 == null)
                        return false;

                    if (item1.m_pItemBase.nClass == ItemBase.ItemClass.ClassOneHandSword && pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassOneHandSword)
                    {
                        if (this.GetCurrentPassiveSkillLevel(1181) < 1 && this.GetCurrentPassiveSkillLevel(61010) < 1)
                            pos = ItemBase.ItemWearType.WearWeapon;
                    }
                    else if (item1.m_pItemBase.nClass == ItemBase.ItemClass.ClassDagger && pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDagger)
                    {
                        if (this.GetCurrentPassiveSkillLevel(61010) < 1)
                            pos = ItemBase.ItemWearType.WearWeapon;
                    }
                    else if (item1.m_pItemBase.nClass == ItemBase.ItemClass.ClassOneHandAxe && pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassOneHandAxe)
                    {
                        if (this.GetCurrentPassiveSkillLevel(61015) < 1)
                            pos = ItemBase.ItemWearType.WearWeapon;
                    }
                }
            }

            if (pos == ItemBase.ItemWearType.WearDecoShield)
            {
                if (pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoOneHandSword
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoTwoHandSword
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoDagger
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoTwoHandSpear
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoTwoHandAxe
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoOneHandMace
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoTwoHandMace
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoHeavyBow
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoLightBow
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoCrossBow
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoOneHandStaff
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoTwoHandStaff
                  || pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoOneHandAxe)
                {
                    item1 = this.m_anWear[1];
                    item2 = this.m_anWear[0];
                    if (item1 != null 
                            && item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassOneHandSword 
                            && item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassDagger 
                            && item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassOneHandAxe
                      || item2 == null
                      || item2.m_pItemBase.nClass != ItemBase.ItemClass.ClassOneHandSword
                            && item2.m_pItemBase.nClass != ItemBase.ItemClass.ClassDagger 
                            && item2.m_pItemBase.nClass != ItemBase.ItemClass.ClassOneHandAxe
                      || this.m_anWear[14] == null
                      || this.GetCurrentPassiveSkillLevel(1181) < 1
                            && this.GetCurrentPassiveSkillLevel(61010) < 1
                            && this.GetCurrentPassiveSkillLevel(61015) < 1)
                        pos = ItemBase.ItemWearType.WearDecoWeapon;
                }
                else
                {
                    item1 = this.m_anWear[1];
                    item2 = this.m_anWear[0];
                    if (item1 != null && item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassShield
                      || item2 != null && item2.m_pItemBase.WearType == ItemBase.ItemWearType.WearTwoHand)
                        return false;
                }
            }
            if (pItem.GetWearType() == ItemBase.ItemWearType.WearTwoHand)
                pos = ItemBase.ItemWearType.WearWeapon;
            if (pos == ItemBase.ItemWearType.WearTwoFingerRing)
                pos = ItemBase.ItemWearType.WearRing;
            item1 = this.m_anWear[9];
            if (item1 != null)
            {
                if (item1.GetWearType() != ItemBase.ItemWearType.WearTwoFingerRing && pItem.GetWearType() == ItemBase.ItemWearType.WearRing)
                    pos = ItemBase.ItemWearType.WearSecondRing;
            }
            if (pos == ItemBase.ItemWearType.WearBagSlot)
            {
                item1 = this.m_anWear[23];
                if (item1 != null)
                {
                    if (item1.m_Instance.Code != pItem.m_Instance.Code)
                    {
                        nCurrentVarIdx = -1;
                        for(i = 0; i < ItemBase.MAX_OPTION_NUMBER; ++i)
                        {
                            if(item1.m_pItemBase.nOptType[i] == 20)
                            {
                                nCurrentVarIdx = i;
                                break;
                            }
                        }
                        int nCurrentVarIdx2 = -1;
                        for(i = 0; i < ItemBase.MAX_OPTION_NUMBER; ++i)
                        {
                            if(pItem.m_pItemBase.nOptType[i] == 20)
                            {
                                nCurrentVarIdx2 = i;
                                break;
                            }
                        }

                        if (nCurrentVarIdx == -1)
                            return false;
                        if (nCurrentVarIdx2 == -1)
                            return false;

                        current_bag_capacity = this.m_fItemMod * item1.m_pItemBase.fOptVar1[nCurrentVarIdx];
                        new_bag_capacity = this.m_fItemMod * pItem.m_pItemBase.fOptVar1[nCurrentVarIdx2];
                        if(current_bag_capacity != new_bag_capacity 
                           && this.m_fWeight <= this.m_Attribute.nMaxWeight
                           && this.m_fWeight > this.m_Attribute.nMaxWeight - current_bag_capacity + new_bag_capacity
                           || this.m_fWeight > this.m_Attribute.nMaxWeight
                           && current_bag_capacity > new_bag_capacity)
                            return false;
                    }
                }
            }
            if (pos != ItemBase.ItemWearType.WearDecoWeapon && pos != ItemBase.ItemWearType.WearDecoShield)
            {
            }
            else
            {
                item1 = this.m_anWear[pos != ItemBase.ItemWearType.WearDecoWeapon ? 1 : 0];
                if (item1 == null || (int)item1.m_pItemBase.nClass > (int) ItemBase.ItemClass.ClassShield)
                    return false;
                switch (item1.m_pItemBase.nClass)
                {
                    case ItemBase.ItemClass.ClassShield:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoShield)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassOneHandSword:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoOneHandSword)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassTwoHandSword:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoTwoHandSword)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassDagger:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoDagger)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassSpear:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoTwoHandSpear)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassTwoHandAxe:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoTwoHandAxe)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassOneHandMace:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoOneHandMace)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassTwoHandMace:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoTwoHandMace)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassHeavyBow:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoHeavyBow)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassLightBow:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoLightBow)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassCrossBow:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoCrossBow)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassOneHandStaff:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoOneHandStaff)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassTwoHandStaff:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoTwoHandStaff)
                            return false;
                        break;

                    case ItemBase.ItemClass.ClassOneHandAxe:
                        if (pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoOneHandAxe)
                            return false;
                        break;

                    default:
                        return false;
                }
            }
            if ((int)pos >= 24 || (int)pos < 0)
                return false;

            if (vpOverlappItemList != null)
            {
                if (this.m_anWear[(int)pos] != null)
                {
                    vpOverlappItemList.Add((int)pos);
                }
                if (pItem.m_pItemBase.WearType == ItemBase.ItemWearType.WearTwoHand)
                {
                    if (this.m_anWear[1] != null)
                    {
                        if ( !pItem.IsBow() && pItem.m_pItemBase.nClass != ItemBase.ItemClass.ClassCrossBow
                          || this.m_anWear[1].m_pItemBase.nGroup != (int)ItemBase.ItemGroup.Bullet)
                        {
                            vpOverlappItemList.Add(1);
                        }
                        if (this.m_anWear[15] != null)
                        {
                            vpOverlappItemList.Add(15);
                        }
                    }
                }
                if (pos == ItemBase.ItemWearType.WearShield)
                {
                    item1 = this.m_anWear[15];
                    if(item1 != null)
                    {
                        if (pItem.m_pItemBase.nClass == ItemBase.ItemClass.ClassShield && item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassDecoShield)
                            vpOverlappItemList.Add(15);

                        if (item1.m_pItemBase.nClass == ItemBase.ItemClass.ClassDecoShield)
                            vpOverlappItemList.Add(15);
                    }
                }
                item1 = this.m_anWear[0];
                if (item1 != null)
                {
                    if (item1.m_pItemBase.WearType == ItemBase.ItemWearType.WearTwoHand)
                    {
                        if (pos == ItemBase.ItemWearType.WearShield)
                        {
                            if (!item1.IsBow() && item1.m_pItemBase.nClass != ItemBase.ItemClass.ClassCrossBow
                              || pItem.m_pItemBase.nGroup != (int)ItemBase.ItemGroup.Bullet)
                            {
                                vpOverlappItemList.Add(0);
                            }
                        }
                    }
                }
                
                if (this.m_anWear[10] != null && pItem.GetWearType() == ItemBase.ItemWearType.WearTwoFingerRing)
                    vpOverlappItemList.Add(10);

                item1 = this.m_anWear[9];
                if (item1 != null)
                {
                    if (item1.GetWearType() == ItemBase.ItemWearType.WearTwoFingerRing)
                    {
                        if (pItem.GetWearType() == ItemBase.ItemWearType.WearRing)
                        {
                            vpOverlappItemList.Add(9);
                        }
                    }
                }
            }

            return true;
        }


        public int GetHuntaholicPoint()
        {
            int result;

            Item hc = this.m_Inventory.FindByCode(806808);
            if (hc != null)
                result = hc.m_Instance.nCurrentEndurance;
            else
                result = 0;
            return result;
        }

        public void SetHuntaholicPoint(int nPoint)
        {

            Item card;

            if (nPoint >= 0)
            {
                if ( nPoint > 2000000000 )
                    nPoint = 2000000000;
            }
            else
            {
                nPoint = 0;
            }

            card = m_Inventory.FindByCode(806808);
            if (card != null)
            {
                if (card.m_Instance.nCurrentEndurance != nPoint )
                {
                    if (nPoint != 0)
                    {
                        card.SetCurrentEndurance(nPoint);
                        if (m_bIsLogin)
                            Messages.SendItemMessage(this,card);
                    }
                    else
                    {
                        card = this.PopItem(card, card.m_Instance.nCount, true);
                        Item.PendFreeItem(card);
                    }
                }
            }
            else
            {
                if (nPoint != 0)
                {
                    card = Item.AllocItem(0,806808,1,ItemInstance.GenerateCode.ByScript,-1,-1,-1,-1,0,0,0,0,-1, Elemental.Type.TypeNone, 0,0,0);
                    card.m_bIsVirtualItem = true;
                    card.SetCurrentEndurance(nPoint);

                    Item nc = this.PushItem(card,1,true);
                    if (!nc.IsSameObject(card))
                    {
                        Item.PendFreeItem(card);
                        if (nc.m_Instance.nCurrentEndurance > 2000000000)
                            nc.SetCurrentEndurance(2000000000);
                    }
                }
            }
            Messages.SendPropertyMessage(this, this.m_hHandle, "huntaholicpoint", nPoint);
        }

        public bool IsMixable(Item pItem)
        {
            return this.IsErasable(pItem);
        }

        public bool IsErasable(Item pItem)
        {

            bool result = pItem.IsInInventory();
            if (result)
            {
                if (pItem.m_Instance.OwnerHandle == this.m_hHandle)
                {
                    if (pItem.m_Instance.nWearInfo == ItemBase.ItemWearType.WearNone)
                    {
                        if (pItem.m_pItemBase.nGroup != 10 || pItem.m_hBindedTarget == 0)
                        {
                            int i = 0;

                            while (true)
                            {
                                if (pItem.m_pItemBase.nGroup == 13 )
                                {
                                    if (this.m_aBeltSlotCard[i] != null && pItem.m_hHandle == this.m_aBeltSlotCard[i].m_hHandle)
                                        break;
                                    if (this.m_aBindSummonCard[i] != null && pItem.m_hHandle == this.m_aBindSummonCard[i].m_hHandle)
                                        break;
                                }
                                ++i;
                                if (i >= 6 )
                                {
                                    if (pItem.m_pItemBase.nGroup != 18
                                      || pItem.m_pPet == null
                                      || !pItem.m_pPet.bIsInWorld )
                                        return !pItem.IsInStorage();
                                    break;
                                }
                            }
                        }
                    }
                }
                result = false;
            }
            return result;
        }

        public bool IsSellable(Item pItem)
        {
            bool result;

            if (!this.IsErasable(pItem) || (pItem.m_Instance.Flag & (uint)ItemInstance.FlagBits.Taming) != 0)
                result = false;
            else
                result = (pItem.m_pItemBase.Flag & (uint)ItemBase.ItemFlag.FlagCantSell) == 0;
            return result;

        }
// Function       :   public bool StructPlayer::IsTradable(struct StructItem *)
// Function       :   public bool StructPlayer::IsDropable(struct StructItem *)

        public bool IsTakeable(uint ItemHandle, long cnt)
        {
            Item pItem;
            pItem = Item.FindItem(ItemHandle);

            if(pItem == null)
                return false;
            float itemWeight = cnt == 0 ? pItem.GetWeight() : pItem.GetWeight(cnt);
            return (!pItem.IsQuestItem()
                 || this.m_QuestManager.IsTakeableQuestItem(pItem.m_Instance.Code)
                 || pItem.IsInStorage())
                && (!pItem.IsJoinable() || this.m_Attribute.nMaxWeight  >= (int)itemWeight + this.m_fWeight);
        }
        
        public Item PushItem(Item item, long cnt, bool bSkipUpdateItemToDB)
        {
            if (item.m_Instance.nOwnerUID == this.m_nUID )
            {
                Globals.Log.Error("Player.AddItem() :: Tried to push already owned item: {0} : {1}", item.m_Instance.UID, this.m_hHandle);
                return null;
            }
            if (item.m_Instance.Code == 0)
            {
                // no code so this must be gold instead
                long nPrevGoldAmount = this.m_nGold;
                long gold = this.m_nGold + item.m_Instance.nCount;
                if (this.ChangeGold(gold) != 0)
                {
                    Globals.Log.Error("ChangeGold/ChangeStorageGold Failed: Case[2], Player[{0}], Info[Inven({1}), Add({2}), bSkipDBUpdate({3})]", 
                        this.m_szName, nPrevGoldAmount,gold, bSkipUpdateItemToDB);
                }
                Item.PendFreeItem(item);
                return null;
            }
            if (item.m_Instance.nIdx == 0)
            {
                this.m_Inventory.m_nIndex++;
                item.m_Instance.nIdx = this.m_Inventory.m_nIndex;
                item.m_bIsNeedUpdateToDB = true;
            }
            Item ni = this.m_Inventory.Push(item, cnt, bSkipUpdateItemToDB);
            this.m_QuestManager.UpdateQuestStatusByItemCount(ni.m_Instance.Code, ni.m_Instance.nCount);
            return ni;

        }

        public Item PopItem(Item pItem, long cnt, bool bSkipUpdateToDB)
        {
            if (pItem != null
              && cnt != 0
              && pItem.m_Instance.nCount >= cnt
              && pItem.m_Instance.OwnerHandle == this.m_hHandle
              && pItem.IsInInventory())
            {
                Item nc = this.popItem(pItem,cnt, bSkipUpdateToDB);
                if(nc != null)
                {
                    nc.m_Instance.nIdx = 0;
                    nc.m_bIsNeedUpdateToDB = true;
                    if (!nc.IsSameObject(pItem))
                        nc.SetOwnerInfo(0, 0, 0);
                    return nc;
                }
            }
            return null;
        }
// Function       :   public struct StructItem * StructPlayer::DropItem(struct StructItem *, const __int64 &)
// Function       :   public void StructPlayer::ChangeItemPosition(bool, unsigned int, unsigned int)

        public ushort ArrangeItem(bool bIsStorage)
        {
            if ( bIsStorage && !this.m_bIsUsingStorage)
                return 5;
            uint ct = Globals.GetArTime();
            if (!bIsStorage)
            {
                if (this.m_nLastInvenArrangedTime + 3000 <= ct)
                {
                    this.m_Inventory.Arrange();
                    this.m_nLastInvenArrangedTime = ct;
                    return 0;
                }
                return 22;
            }
            if (this.m_nLastStorageArrangedTime + 3000 > ct)
                return 22;
            this.m_Storage.Arrange();
            this.m_nLastStorageArrangedTime = ct;
            return 0;

        }

        public bool EraseBullet(long count)
        {
            bool result;

            Item item = this.GetWornItem(ItemBase.ItemWearType.WearShield);
            if (item != null && item.m_pItemBase.nGroup == 98 && item.m_Instance.nCount >= count)
            {
                long nc = item.m_Instance.nCount - count;
                this.m_QuestManager.UpdateQuestStatusByItemCount(item.m_Instance.Code, nc);
                if (item.m_Instance.nCount == count)
                    this.Putoff(ItemBase.ItemWearType.WearShield);

                result = this.eraseItem(item, count);
            }
            else
            {
                result = false;
            }
            return result;

        }

        public bool EraseItem(Item pItem, long count)
        {
            this.m_Inventory.Erase(pItem, count, false);
            return true;
        }

        public bool EraseSummon(Summon pSummon)
        {
            if (pSummon == null)
                return false;

            if (this.m_vSummonList.Contains(pSummon))
                this.m_vSummonList.Remove(pSummon);

            pSummon.m_master = null;
            Messages.SendRemoveSummonMessage(this, pSummon);
            pSummon.DBQuery(new DB_DeleteSummon(pSummon));
            return true;
        }

// Function       :   public bool StructPlayer::GiveItem(struct StructPlayer *, unsigned int, const __int64 &, unsigned int *)
// Function       :   public const __int64 StructPlayer::GetItemCount(int)
        public uint GetItemCount()
        {
              return (uint) m_Inventory.m_vList.Count;
        }

        public uint GetStorageItemCount()
        {
            return (uint)m_Storage.m_vList.Count;
        }

        public Item GetItem(uint idx)
        {
              return this.m_Inventory.m_vList[(int)idx];
        }

        public Item GetStorageItem(uint idx)
        {
            return this.m_Storage.m_vList[(int)idx];
        }

        public Item FindItemByCode(int code)
        {
            return this.m_Inventory.FindByCode(code);
        }
        public Item FindItemBySID(long uid)
        {
            return this.m_Inventory.FindBySID(uid);
        }

        public Item FindStorageItem(int code)
        {
            return this.m_Storage.FindByCode(code);
        }

        public Item FindEmptySummonCard(int code)
        {
            return this.m_Inventory.Find(code, (uint)ItemInstance.FlagBits.Summon, false);
        }

        public Item FindEmptyPetCage(int code)
        {
            return this.m_Inventory.Find(code, (uint)ItemInstance.FlagBits.ContainsPet, false);
        }

        public Item FindTamingSummonCard(int code)
        {
            return this.m_Inventory.Find(code, (uint)ItemInstance.FlagBits.Taming, true);
        }

        public ushort UseItem(Item pItem, Creature pTarget, string szParameter)
        {
            int nCode;                              // -92  -5Ch
            uint nContactNPCHandle;                 // -80  -50h
            Item.TargetType eTargetType;            // -76  -4Ch
            string strOnUseItem;                    // -72  -48h
            string strScript;                       // -44  -2Ch
            ushort result;
// .text:0045FF41 pItem           = dword ptr  8
// .text:0045FF41 pTarget         = dword ptr  0Ch
// .text:0045FF41 szParameter     = dword ptr  10h
// 
// Data           :   ebp Relative, [00000008], Param, Type: struct StructItem *, pItem
// Data           :   ebp Relative, [0000000C], Param, Type: struct StructCreature *, pTarget
// Data           :   ebp Relative, [00000010], Param, Type: const char *, szParameter

            if (pTarget == null)
                pTarget = this;
            if (pItem.m_Instance.nCount < 1 )
                return 6;

            for(int i = 0; i < ItemBase.MAX_OPTION_NUMBER; ++i)
            {
                if (pItem.m_pItemBase.nBaseType[i] != 0)
                {
                    result = pTarget.onItemUseEffect(this, pItem, pItem.m_pItemBase.nBaseType[i], pItem.m_pItemBase.fBaseVar1[i], pItem.m_pItemBase.fBaseVar2[i], szParameter);
                    if (result != 0)
                        return result;
                }

                if (pItem.m_pItemBase.nOptType[i] != 0)
                {
                    result = pTarget.onItemUseEffect(this, pItem, pItem.m_pItemBase.nOptType[i], pItem.m_pItemBase.fOptVar1[i], pItem.m_pItemBase.fOptVar2[i], szParameter);
                    if (result != 0)
                        return result;
                }
            }

            if (pItem.m_pItemBase.strScript.Length > 0)
            {
                strScript = pItem.m_pItemBase.strScript;

                if (strScript.Contains("on_use_item"))
                {
                    eTargetType = Item.TargetType.Unknown;
                    nCode = 0;
                    if (pTarget.IsPlayer())
                    {
                        eTargetType = Item.TargetType.Player;
                    }
                    else if (pTarget.IsSummon())
                    {
                        eTargetType = Item.TargetType.Summon;
                        nCode = (pTarget as Summon).GetSummonCode();
                    }
                    else if (pTarget.IsMonster())
                    {
                        eTargetType = Item.TargetType.Monster;
                        nCode = (pTarget as Monster).GetMonsterId();
                    }
                    else if (pTarget.IsNPC())
                    {
                        nCode = (pTarget as NPC).m_BaseInfo.id;
                        eTargetType = Item.TargetType.NPC;
                    }

                    int nf = 0;
                    if(eTargetType == Item.TargetType.Summon && (pTarget as Summon).m_master.m_hHandle == this.m_hHandle)
                        nf = 1;
                    strOnUseItem = String.Format("on_use_item( {0}, {1}, {2}, {3}, {4}, {5} )", 
                        pItem.m_Instance.Code, this.m_hHandle, (int)eTargetType, pTarget.m_hHandle, nCode, nf);

                    strScript = strScript.Replace("on_use_item", strOnUseItem);
                }

                nContactNPCHandle = this.GetLastContactLong("npc");
                this.SetLastContact("npc", 0);

                LuaVM.Instance.RunString(this, strScript);
                this.SetLastContact("npc", nContactNPCHandle);
            }

            if (pItem.m_pItemBase.nCoolTimeGroup != 0)
            {
                uint ct = Globals.GetArTime();
                this.m_nItemCoolTime[pItem.m_pItemBase.nCoolTimeGroup-1] = (uint)(ct + (100 * pItem.m_pItemBase.nCoolTime));
                Messages.SendItemCoolTimeInfo(this);
            }

            if (pItem.m_Instance.Code != 910006 )
            {
                if (pItem.m_Instance.Code != 910009 )
                {
                    if (pItem.m_Instance.Code != 930040 )
                    {
                        if (pItem.m_Instance.Code != 930042 )
                        {
                            if (pItem.m_Instance.Code != 2010459 )
                            {
                                if (pItem.m_Instance.Code != 2902104 )
                                {
                                    if (pItem.m_Instance.Code != 9000098 )
                                    {
                                        if (pItem.m_pItemBase.nType != 6 )
                                        {
//                                            this.EraseItem(pItem, 1);
                                        }
                                        if (pItem.IsCashItem())
                                            this.Save(false);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return 0;
        }


        public int IsUseableItem(Item pItem, Creature pTarget)
        {
            uint ct = Globals.GetArTime();

            if (pItem.m_pItemBase.nCoolTimeGroup < 0 || pItem.m_pItemBase.nCoolTimeGroup > 40 || pItem.m_pItemBase.nCoolTimeGroup != 0 
                && this.m_nItemCoolTime[pItem.m_pItemBase.nCoolTimeGroup-1] > ct)
                return 22;
            if ((pItem.m_pItemBase.Flag & 0x1000) == 0 || this.m_fWeight / this.m_Attribute.nMaxWeight <= 0.5)
            {
                if ((this.m_nRideIdx != 0 || this.m_nRidingStateUid != 0) && (pItem.m_pItemBase.Flag  & 0x4000) != 0)
                    return 35;

                if (pItem.m_pItemBase.nMaxLevel != 0 && pItem.m_pItemBase.nMaxLevel < this.GetLevel())
                    return 16;
                if (pItem.m_pItemBase.nMinLevel <= this.GetLevel())
                {
                    if (pTarget == null)
                        return 0;

                    if (pItem.m_pItemBase.nTargetMaxLevel != 0
                      && pItem.m_pItemBase.nTargetMaxLevel < pTarget.GetLevel())
                        return 16;
                    if (pItem.m_pItemBase.nTargetMinLevel <= pTarget.GetLevel())
                        return 0;
                }
                return 17;
            }
            return 11;
        }

        public uint GetItemCoolTime(int group_id)
        {
            if (group_id < 1 || group_id > 40)
                return 0;
            return this.m_nItemCoolTime[group_id-1];
        }

        public void CloseStorage()
        {
            this.m_bIsUsingStorage = false;
        }
// Function       :   public bool IsUsingStorage()

        public bool MoveStorageToInventory(Item pItem, long cnt)
        {
            bool result;
            Item pNewItem;      //Data           :   ebp Relative, [0000007C], Local, Type: struct StructItem *, 
            Item pDividedItem;  //Data           :   ebp Relative, [00000078], Local, Type: struct StructItem *, 
            long nResultCnt;    //Data           :   ebp Relative, [00000068], Local, Type: __int64, nResultCnt


            if (this.m_bIsUsingStorage
              && pItem.IsInStorage()
              && this.m_Storage.check(pItem)
              && pItem.m_nAccountID == this.m_nAccountID
              && pItem.m_Instance.nCount >= cnt
              && pItem.IsJoinable() || pItem.m_Instance.nCount == cnt
              && this.IsTakeable(pItem.m_hHandle, cnt))
            {
                if (pItem.IsJoinable())
                {
                    nResultCnt = pItem.m_Instance.nCount - cnt;
                    pNewItem = this.m_Storage.Pop(pItem, cnt, false);
                    this.m_Inventory.m_nIndex++;
                    pNewItem.m_Instance.nIdx = this.m_Inventory.m_nIndex;
                    pNewItem.m_bIsNeedUpdateToDB = true;
                    pDividedItem = this.m_Inventory.Push(pNewItem, cnt, false);
                    this.m_QuestManager.UpdateQuestStatusByItemCount(pItem.m_Instance.Code, pDividedItem.m_Instance.nCount);
                    if (pItem.m_hHandle != pNewItem.m_hHandle)
                    {
                        pItem.DBQuery(new DB_UpdateItem(pItem));
                    }
                    if (pDividedItem.m_hHandle != pNewItem.m_hHandle)
                        Item.PendFreeItem(pNewItem);
                }
                else
                {
                    this.m_Storage.Pop(pItem, cnt, false);
                    this.m_Inventory.m_nIndex++;
                    pItem.m_Instance.nIdx = this.m_Inventory.m_nIndex;
                    pItem.m_bIsNeedUpdateToDB = true;
                    this.m_Inventory.Push(pItem, cnt, false);
                }
                result = true;
            }
            else
            {
                result = false;
            }
            return result;
        }

        public bool MoveInventoryToStorage(Item pItem, long cnt)
        {
            bool result;
            Item pNewItem;      //Data           :   ebp Relative, [0000007C], Local, Type: struct StructItem *, 
            Item pDividedItem;  //Data           :   ebp Relative, [00000078], Local, Type: struct StructItem *, 
            long nResultCnt;    //Data           :   ebp Relative, [00000068], Local, Type: __int64, nResultCnt


            if (this.IsErasable(pItem)
              && (pItem.m_pItemBase.Flag & 2) == 0
              && (pItem.m_Instance.Flag & 0x20000000) == 0
              && this.m_bIsUsingStorage
              && pItem.m_Instance.nCount >= cnt
              && (pItem.IsJoinable() || pItem.m_Instance.nCount == cnt))
            {
                if (pItem.IsJoinable())
                {
                    nResultCnt = pItem.m_Instance.nCount - cnt;
                    this.m_QuestManager.UpdateQuestStatusByItemCount(pItem.m_Instance.Code, nResultCnt);
                    pDividedItem = this.m_Inventory.Pop(pItem, cnt, false);
                    this.m_Storage.m_nIndex++;
                    pDividedItem.m_Instance.nIdx = this.m_Storage.m_nIndex;
                    pDividedItem.m_bIsNeedUpdateToDB = true;
                    pNewItem = this.m_Storage.Push(pDividedItem, cnt, false);

                    if (pItem.m_hHandle != pDividedItem.m_hHandle)
                    {
                        pItem.DBQuery(new DB_UpdateItem(pItem));
                    }
                    if (pNewItem.m_hHandle != pDividedItem.m_hHandle)
                        Item.PendFreeItem(pDividedItem);
                }
                else
                {
                    this.m_Inventory.Pop(pItem, cnt, false);
                    this.m_Storage.m_nIndex++;
                    pItem.m_Instance.nIdx = this.m_Storage.m_nIndex;
                    pItem.m_bIsNeedUpdateToDB = true;
                    this.m_Storage.Push(pItem, cnt, false);
                }
                result = true;
            }
            else
            {
                result = false;
            }
            return result;

            if (this.m_bIsUsingStorage
              && pItem.IsInStorage()
              && this.m_Storage.check(pItem)
              && pItem.m_nAccountID == this.m_nAccountID
              && pItem.m_Instance.nCount >= cnt
              && pItem.IsJoinable() || pItem.m_Instance.nCount == cnt
              && this.IsTakeable(pItem.m_hHandle, cnt))
            {
                if (pItem.IsJoinable())
                {
                    nResultCnt = pItem.m_Instance.nCount - cnt;
                    pNewItem = this.m_Storage.Pop(pItem, cnt, false);
                    this.m_Inventory.m_nIndex++;
                    pNewItem.m_Instance.nIdx = this.m_Inventory.m_nIndex;
                    pNewItem.m_bIsNeedUpdateToDB = true;
                    pDividedItem = this.m_Inventory.Push(pNewItem, cnt, false);
                    this.m_QuestManager.UpdateQuestStatusByItemCount(pItem.m_Instance.Code, pDividedItem.m_Instance.nCount);
                    if (pItem.m_hHandle != pNewItem.m_hHandle)
                    {
                        pItem.DBQuery(new DB_UpdateItem(pItem));
                    }
                    if (pDividedItem.m_hHandle != pNewItem.m_hHandle)
                        Item.PendFreeItem(pNewItem);
                }
                else
                {
                    this.m_Storage.Pop(pItem, cnt, false);
                    this.m_Inventory.m_nIndex++;
                    pItem.m_Instance.nIdx = this.m_Inventory.m_nIndex;
                    pItem.m_bIsNeedUpdateToDB = true;
                    this.m_Inventory.Push(pItem, cnt, false);
                }
                result = true;
            }
            else
            {
                result = false;
            }
            return result;
        }

// Function       :   public struct StructInventory * GetInventory()

        public void UpdateWeightWithInventory()
        {
            this.m_fWeight = this.m_Inventory.m_fWeightModifier + this.m_Inventory.m_fWeight; 
        }
// Function       :   public void EqipSummon(unsigned int *, unsigned int)
        public void AddSummon(Summon summon, bool bSendMsg)
        {
            this.m_vSummonList.Add(summon);
            if (bSendMsg)
                Messages.SendAddSummonMessage(this, summon);
            if (summon.IsLoginComplete())
            {
                summon.DBQuery(new DB_UpdateSummon(summon, false));
            }

        }

        public void RemoveSummon(Summon pSummon)
        {
            if(this.m_vSummonList.Contains(pSummon))
                this.m_vSummonList.Remove(pSummon);
            
            pSummon.m_master = null;
            Messages.SendRemoveSummonMessage(this, pSummon);
            pSummon.DBQuery(new DB_UpdateSummon(pSummon, false));
        }

        public void AddSummonToStorage(Summon pSummon)
        {
            pSummon.m_nAccountId = this.m_nAccountID;
            this.m_vStorageSummonList.Add(pSummon);

            if (pSummon.IsLoginComplete())
            {
                pSummon.DBQuery(new DB_UpdateSummon(pSummon,false));
            }
        }
        
        public void RemoveSummonFromStorage(Summon pSummon)
        {
            if(this.m_vStorageSummonList.Contains(pSummon))
                this.m_vStorageSummonList.Remove(pSummon);

            pSummon.m_nAccountId = 0;
            pSummon.DBQuery(new DB_UpdateSummon(pSummon, false));
        }

        public void RemoveAllSummonFromWorld()
        {
            RLock rl;
            AutoLock al;
            foreach (Summon s in this.m_vSummonList)
            {
                if (s.bIsInWorld)
                {
                    rl = RappelzServer.Instance._LockObjectWithVisibleRange(s);
                    al = new AutoLock(rl.handle);

                    GameContent.RemoveSummonFromWorld(s);
                    // remove al
                }
            }
            this.procPendingUnSummon();
        }


        public void RemoveAllPetFromWorld()
        {
            RLock rl;
            AutoLock al;
            foreach (Pet s in this.m_vPetList)
            {
                if (s.bIsInWorld)
                {
                    rl = RappelzServer.Instance._LockObjectWithVisibleRange(s);
                    al = new AutoLock(rl.handle);

                    GameContent.RemovePetFromWorld(s);
                    // remove al
                }
            }
            this.procPendingUnSummonPet();
        }

        public Summon GetSummon(uint handle)
        {
            foreach(Summon s in this.m_vSummonList)
            {
                if(s.m_hHandle == handle)
                    return s;
            }
            return null;
        }

        public Summon GetSummon(int summon_sid)
        {
            foreach (Summon s in m_vSummonList)
            {
                if(s.GetSummonSID() == summon_sid)
                    return s;
            }
            return null;
        }

        public Summon GetSummonAt(int slot_index)
        {
            Item i = m_aBindSummonCard[slot_index];
            if(i != null)
                return i.m_pSummon;
            return null;
        }
// Function       :   public struct StructItem * GetSummonCardAt(int)
// Function       :   public void SetSummonCardAt(int, struct StructItem *)

        public bool Summon(Summon pSummon, ArPosition pos)
        {
            if (!this.m_bIsSummonable)
                return false;

            if (pSummon.bIsInWorld || this.m_pSubSummon != null && this.m_pMainSummon != null)
                return false;
            if (GameRule.bLimitDungeonEnterableLevel)
            {
//                 pSummona = this->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.y;
//                 v12 = this->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.x;
//                 v7 = DungeonManager::Instance();
//                 if ( DungeonManager::GetDungeonID(v7, v12, pSummona) )
//                 {
//                     v8 = v6->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr[3].IsDeleteable(v6);
//                     if ( v8 > v3->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr[3].IsDeleteable(v3) )
//                         return 0;
//                     v4 = 0;
//                 }
            }
            if ((pSummon.m_StatusFlag & StatusFlags.Invincible) != 0)
                pSummon.m_StatusFlag &= ~StatusFlags.Invincible;

            if (this.m_pMainSummon != null)
            {
                this.m_pSubSummon = this.m_pMainSummon;
                this.m_nNextUnSummonTime = this.m_nDoubleSummonTime + Globals.GetArTime();
                using(PacketOut unPak = new PacketOut(ClientOutPackets.UnsummonNotice))
                {
                    unPak.WriteUInt32(this.m_pSubSummon.m_hHandle);
                    unPak.WriteUInt32(this.m_nDoubleSummonTime);
                    this.Connection.SendTCP(unPak);
                }
            }
            this.m_pMainSummon = pSummon;
            pSummon.SetCurrentXY(pos.x, pos.y);
            pSummon.m_layer = this.m_layer;
            pSummon.StopMove();
            if (pSummon.m_nHP == 0)
                pSummon.m_nDeadTime = Globals.GetArTime();
            GameContent.AddSummonToWorld(pSummon);

            RappelzServer.Instance.SetObjectPriority(pSummon, Priority.Normal);
            pSummon.m_StatusFlag |= StatusFlags.NeedToCalculateStat;
            return true;
        }

        public bool UnSummon(Summon pSummon)
        {
            bool result;

            if (pSummon != null)
                result = this.unSummon(pSummon);
            else if (this.m_pSubSummon != null)
                result = this.unSummon(this.m_pSubSummon);
            else if (this.m_pMainSummon != null)
                result = this.unSummon(this.m_pMainSummon);
            else
                result = false;
            return result;
        }

        public bool PendUnSummon(Summon summon)
        {
            return false;
        }
// Function       :   public int GetPendingUnSummon()
// Function       :   public struct StructSummon * GetMainSummon()
// Function       :   public struct StructSummon * GetSubSummon()
// Function       :   public bool IsSummonable()
// Function       :   public int GetNextUnSummonTime()
// Function       :   public struct StructItem * GetBeltSlotCardAt(int)
// Function       :   public void SetNextUnSummonTime(int)
// Function       :   public bool IsSummonEXPLimited()
// Function       :   public void SetNameChangeTarget(const int)
// Function       :   public int GetNameChangeTarget()
        public void AddPet(Pet pet, bool  bSendMsg)
        {
            lock(this.m_vPetList)
            {
                this.m_vPetList.Add(pet);
                if(bSendMsg)
                    Messages.SendAddPetMessage(this,pet);

                pet.m_master = this;

                if (pet.IsLoginComplete())
                    pet.DBQuery(new DB_UpdatePet(pet));
            }
        }

        public void RemovePet(Pet pet)
        {
//            this->m_csPet.baseclass_0.vfptr->Lock(&this->m_csPet);

            if(this.m_vPetList.Contains(pet))
                this.m_vPetList.Remove(pet);

            pet.m_master = null;
            Messages.SendRemovePetMessage(this, pet);
            pet.DBQuery(new DB_UpdatePet(pet));
//            (*(v9 + 12))(v4);
        }

        public void AddPetToStorage(Pet pet)
        {
            pet.m_master = null;
            this.m_vStoragePetList.Add(pet);

            if (pet.IsLoginComplete())
            {
                pet.DBQuery(new DB_UpdatePet(pet));
            }
        }

        public void RemovePetFromStorage(Pet pet)
        {
            if(this.m_vStoragePetList.Contains(pet))
                this.m_vStoragePetList.Remove(pet);

            pet.m_master = null;
            pet.DBQuery(new DB_UpdatePet(pet));
        }

        public ushort SummonPet(Pet pPet)
        {
// .text:00458293 var_48          = dword ptr -48h
// .text:00458293 var_44          = dword ptr -44h
// .text:00458293 result          = ArPosition ptr -34h
            ArPosition pos;//             = ArPosition ptr -24h
            ArPosition cp;
// .text:00458293 this            = std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > ptr -14h
// .text:00458293 it              = std::_Vector_iterator<StructPet *,std::allocator<StructPet *> > ptr -0Ch
            bool bIsOwnedPet;               //     = byte ptr -1
// .text:00458293 pPet            = dword ptr  8

            bIsOwnedPet = false;
            lock(this.m_vPetList)
            {
                foreach (Pet p in this.m_vPetList)
                {
                    if (p.m_hHandle == pPet.m_hHandle)
                    {
                        bIsOwnedPet = true;
                        break;
                    }
                }
            }
            if ( bIsOwnedPet
              && pPet.m_item != null
              && pPet.m_item.m_Instance.OwnerHandle == this.m_hHandle)
            {
                if (pPet.bIsInWorld )
                    return 6;

                if (this.m_pSummonedPet != null)
                {
                    if(this.m_hHandle == pPet.m_hHandle)
                        return 6;
                    return 9;
                }
                else
                {
                    pos = new ArPosition(this.mv);
                    pPet.SetCurrentXY(pos.x,pos.y);
                    pPet.m_layer = this.m_layer;
                    pPet.StopMove();
                    do
                    {
                        pPet.AddNoise(Globals.GetRandomInt32(), Globals.GetRandomInt32(),70);
                        cp = pPet.GetCurrentPosition(Globals.GetArTime());
                    }
                    while (pos.GetDistance(cp) < 24.0f);
                    RappelzServer.Instance.AddPetToWorld(pPet);

                    RappelzServer.Instance.SetObjectPriority(pPet, Priority.Normal);
                    this.m_pSummonedPet = pPet;
                }
            }
            else
            {
                return 3;
            }
            return 0;
        }

        public bool UnSummonPet()
        {
            return true;
        }
// Function       :   public struct StructPet * GetSummonedPet()
// Function       :   public struct StructPet * StructPlayer::GetPet(int)

        public bool ProcGlobalChatProcess(string pChat, int nChatType)
        {
//.text:00454008 _lock           = ArcadiaAutoLock ptr -50h
            long t;                 // -24  -18h
            int m;                  // -16  -10h
//.text:00454008 pChat           = dword ptr  8
            float fRatio;           // 12   0Ch
            RLock rl;
            AutoLock al;

//Data           :   ebp Relative, [FFFFFFB0], Local, Type: struct tm, local_tm


            PacketOut pak;
            uint ct = Globals.GetArTime();
            if (this.m_nPermission <= 0)
            {
                pak = new PacketOut(ClientOutPackets.ChatResult);
// Enum           :   CHAT_RESULT, Type: int
// Data           :     constant 0x0, Constant, Type: int, RESULT_DECREASE_HPMP
// Data           :     constant 0x1, Constant, Type: int, RESULT_COOLTIME
// Data           :     constant 0x2, Constant, Type: int, RESULT_NEED_MORE_HPMP
// Data           :     constant 0x3, Constant, Type: int, RESULT_LEVEL_RESTRICT
// Data           :   this+0x7, Member, Type: unsigned char, type
// Data           :   this+0x8, Member, Type: unsigned char, percentage
// Data           :   this+0x9, Member, Type: int, result
// Data           :   this+0xD, Member, Type: int, reserved


                if (this.m_nLastGlobalChatTime + 300 > Globals.GetArTime())
                {
                    pak.WriteByte((byte)nChatType);
                    pak.WriteByte(0);
        LABEL_3:
                    pak.WriteInt32(1);
        LABEL_4:
                    pak.WriteInt32(0);
                    this.Connection.SendTCP(pak);
                    return false;
                }

                if (this.GetLevel() < GameRule.nMinGlobalChatUsableLevel)
                {
                    pak.WriteByte((byte)nChatType);
                    pak.WriteByte((byte)GameRule.nMinGlobalChatUsableLevel);
                    pak.WriteInt32(3); // *(v3 - 35) = 3;
                    pak.WriteInt32(0);
                    this.Connection.SendTCP(pak);
                    return false;
                }
                if (nChatType == 2)
                {
//                     v8 = _time64(0);
//                     v9 = this.m_nAdvChatCount == 0;
//                     *(v3 - 24) = v8;
//                     *(v3 - 20) = HIDWORD(v8);
//                     if (this.m_nAdvChatCount != 0)
//                     {
//                         memcpy((v3 - 80), _localtime64(this.m_nLastAdvChatTime), 0x24u);
//                         *(v3 - 72) = 6;
//                         *(v3 - 76) = 0;
//                         *(v3 - 80) = 0;
//                         v10 = _mktime64((v3 - 80));
//                         if (this.m_nLastAdvChatTime > v10 )
//                             v10 += 86400;
//                         if ( __PAIR__(*(v3 - 20), *(v3 - 24)) > v10 )
//                             this.m_nAdvChatCount = 0;
//                     }
//                     if (GameRule.bLimitAdvChatCount && this.m_nAdvChatCount > this.GetLevel() / 10 )
//                     {
//                         pak.WriteByte((byte)nChatType);
//                         pak.WriteByte(0);
//                         pak.WriteInt32(1);
//                         pak.WriteInt32(0);
//                         this.Connection.SendTCP(pak);
//                         return false;
//                     }
//                    v11 = *(v3 - 24);
                    this.m_nAdvChatCount++;
                    this.m_nLastAdvChatTime = ct;
                }
                else
                {
                    m = 1;
                    if (nChatType == 4)
                        m = 2;
                    if (pChat == this.m_strLastGlobalChat)
                        m *= 2;

                    if (this.m_nChatPenalty >= 5 )
                    {
                        fRatio = (float)Math.Pow(this.m_nChatPenalty-4, 2) / 3.0f * 0.01f;
                        int subHP = (int)((float)this.m_nMaxHP * fRatio);
                        int subMP = (int)((float)this.m_nMaxMP * fRatio);

                        pak.WriteByte((byte)nChatType);
                        pak.WriteByte((byte)(fRatio * 100.0));
                        if (this.m_nHP <= subHP || this.m_fMP <= subMP)
                        {
                            pak.WriteInt32(2); // *(v3 - 35) = 3;
                            pak.WriteInt32(0);
                            this.Connection.SendTCP(pak);
                            return false;
                        }

                        this.AddHP(-subHP);
                        this.AddMP(-subMP);
                        pak.WriteInt32(0); // *(v3 - 35) = 3;
                        pak.WriteInt32(0);
                        this.Connection.SendTCP(pak);
                        
                        rl = RappelzServer.Instance._LockObjectWithVisibleRange(this);
                        al = new AutoLock(rl.handle);
                        Messages.BroadcastHPMPMsg(this, -subHP,-subMP,false);
//                        ArcadiaAutoLock::_ArcadiaAutoLock((v3 - 64));
                    }
                    this.m_strLastGlobalChat = pChat;
                    this.m_nChatPenalty += m;
                    this.m_nNextChatPenaltyDecreaseTime = ct + 3000;
                }
                this.m_nLastGlobalChatTime = ct;
            }
            return true;

        }

        public void Login()
        {
            List<Quest> vQuestList = new List<Quest>();

            if (!m_bIsLogin )
            {
                uint ct  = Globals.GetArTime();
                m_nLoginTime = ct;
                m_nLastUpdateTime = ct;
                m_nLastContinuousPlayTimeProcTime = ct;
                m_nLastPlayTimeUpdateTime = ct;
                m_bIsLogin = true;
                m_bHasLogined = true;

                lock(s_vPlayerList)
                {
                    s_vPlayerList.Add(this);
                    m_nPlayerListIndex = s_vPlayerList.Count - 1;
                    m_hsPlayerList.Add(this.m_szName.ToUpper(), this);
                }

//                 v14 = ArcadiaServer.Instance._LockObjectWithVisibleRange((ArcadiaLock *)(v1 - 92),&v2->baseclass_0.baseclass_0.baseclass_0);
//                 ArcadiaAutoLock::ArcadiaAutoLock((ArcadiaAutoLock *)(v1 - 136),v14);
                this.m_QuestManager.GetRelatedQuest(vQuestList,-1);

                foreach(Quest q in vQuestList)
                {
                    this.updateQuestStatus(q);
                }

//                ArcadiaAutoLock::_ArcadiaAutoLock((ArcadiaAutoLock *)(v1 - 136));
            }

        }

        public void LogoutNow(int nCallerIdx)
        {
            int nHuntaholicID;
//            ArcadiaAutoLock, _lock

            if (GameRule.bUseLoginLogoutDebug)
                Globals.Log.Info("LoginLogout_Debug: LogoutNow ({0})", m_szAccountName);

            nHuntaholicID = 0;// HuntaholicManager.Instance.GetHuntaholicID(this);
            if (nHuntaholicID != 0 && m_nPartyId != 0)
            {
/*
                if (HuntaholicManager.Instance.IsHuntaholicDungeon(&v4->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0) )
                {
                    v13 = (v4->baseclass_0.m_nHP != 0) + 1;
                    v14 = *(_DWORD *)(v2 + 124);
                    HuntaholicManager.Instance.QuitHunting(v14, v4, 1, (_HUNTING_RESULT)v13);
                }
                else
                {
                    v16 = *(_DWORD *)(v2 + 124);
                    HuntaholicManager.Instance.LeaveInstanceDungeon(v16, v4);
                }
*/
            }
            if (bIsInWorld)
            {
                this.RemoveAllSummonFromWorld();
                this.RemoveAllPetFromWorld();
            }
            if (m_nCompeteID != 0)
            {
                //CompeteManager.Instance.RetireCompeteWithPlayer(this, 1);
            }
            if (Connection != null)
            {
                lock(Connection.Tag)
                {
                    Connection.Tag.nContinuousPlayTime = GetContinuousPlayTime();
                    Connection.Tag.nContinuousLogoutTime = GetContinuousLogoutTime();
                    Connection.Tag.player = null;
                }
            }

//             v21 = ArcadiaServer::Instance();
//             v22 = ArcadiaServer::_LockObjectWithVisibleRange((ArcadiaLock *)(v2 + 112),
//             &v4->baseclass_0.baseclass_0.baseclass_0,
//             "D:\\alienbrainWork\\Source Code\\@Rappelz\\Server\\GameServer_For_Update\\090721_GameServer\\Game\\Struct\\StructPlayer.cpp",
//             1521);
//             ArcadiaAutoLock::ArcadiaAutoLock(
//             (ArcadiaAutoLock *)(v2 - 120),
//             v22,
//             "D:\\alienbrainWork\\Source Code\\@Rappelz\\Server\\GameServer_For_Update\\090721_GameServer\\Game\\Struct\\StructPlayer.cpp",
//             1521);
//             v23 = v4->baseclass_0.baseclass_0.baseclass_0.bIsInWorld;
//             *(_DWORD *)(v2 - 4) = 0;
            if (bIsInWorld)
            {
                GameContent.RemovePlayerFromWorld(this);
                this.quadTreeItem.RemoveMe();
            }
            if (this.IsUsingSkill())
                this.CancelSkill();
            if (this.m_hTamingTarget != 0)
            {
//                 StructCreature::get((StructCreature::iterator *)(v2 + 104), v4->m_hTamingTarget);
//                 v24 = *(_DWORD *)(v2 + 108) == 0;
//                 *(_BYTE *)(v2 - 4) = 1;
//                 if ( !v24 )
//                 ClearTamer(*(StructMonster **)(v2 + 108), 1);
//                 *(_BYTE *)(v2 - 4) = 0;
//                 *(_DWORD *)(v2 + 104) = &StructCreature::iterator::_vftable_;
//                 GameObject::iterator::_iterator((GameObject::iterator *)(v2 + 104));
            }
            if (this.mv.bIsMoving && this.bIsInWorld )
            {
                this.Step(Globals.GetArTime());
            }

            m_bIsLogin = false;
            this.Save(false);

            ChannelManager.LeavePlayerFromLayer(this.m_layer);

            this.DBQuery(new DB_Logout(this));
            if (m_nWorldLocationId != 0)
            {
                WorldLocationManager.Instance.RemoveFromLocation(this);
                this.m_WorldLocation = null;
            }
            if (m_nPartyId != 0)
            {
                PartyManager.Instance.onLogout(m_nPartyId, this);
                Messages.PrintfPartyChatMessage(100, m_nPartyId, "LOGOUT|{0}|", this.GetName());
            }
            if (m_nGuildId != 0)
            {
                GuildManager.Instance.onLogout(m_nGuildId, this);
                Messages.PrintfGuildChatMessage(110, m_nGuildId, "LOGOUT|{0}|", this.GetName());
            }
            Messages.SendStatusMessageToFriendOfPlayer(this, false);
            if (m_hTarget != 0)
            {
                Creature pTarget = Creature.get(this.m_hTarget) as Creature;
                if (pTarget != null)
                {
                    pTarget.RemoveAimer(this.m_hHandle);
                }
                this.m_hTarget = 0;
            }
            m_nLogoutTime = Globals.GetArTime();
            if (m_hTradeTarget != 0)
            {
                Player tt = Player.get(m_hTradeTarget) as Player;
                if (tt != null)
                    tt.CancelTrade(true);
                this.clearTradeInfo();
            }
            this.RemoveAllHate();
//             v37 = m_nLogoutTime;
//             *(float *)(v2 + 124) = v4->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.y;
//             v38 = *(float *)(v2 + 124);
//             v39 = (v37 - v4->m_nLoginTime) / 0x64;
//             *(_DWORD *)(v2 - 80) = 0;
//             *(_DWORD *)(v2 - 84) = v39;
//             v40 = (unsigned __int64)v38;
//             *(float *)(v2 + 124) = v4->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.x;
//             *(_DWORD *)(v2 - 68) = (unsigned __int64)v38;
//             v41 = *(float *)(v2 + 124);
//             *(_DWORD *)(v2 - 64) = HIDWORD(v40);
//             *(_DWORD *)(v2 + 56) = (unsigned __int64)v41;
//             LODWORD(v40) = v4->baseclass_0.baseclass_0.baseclass_0.layer;
//             *(_DWORD *)(v2 + 60) = (unsigned __int64)v41 >> 32;
//             v40 = (signed int)v40;
//             *(_DWORD *)(v2 - 36) = v40;
//             LODWORD(v40) = v4->m_nStamina;
//             *(_DWORD *)(v2 - 32) = HIDWORD(v40);
//             *(_DWORD *)(v2 - 100) = v40;
//             *(_DWORD *)(v2 - 96) = (unsigned __int64)(signed int)v40 >> 32;
//             v42 = StructPlayer::GetPCBangMode(v4);
//             *(_DWORD *)(v2 + 24) = (char)v42;
//             LODWORD(v42) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 + 28) = HIDWORD(v42);
//             v43 = (*(int (__thiscall **)(StructPlayer *))(v42 + 92))(v4);
//             *(_DWORD *)(v2 - 52) = v43;
//             LODWORD(v43) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 - 48) = HIDWORD(v43);
//             v44 = (*(int (__thiscall **)(StructPlayer *))(v43 + 72))(v4);
//             *(_DWORD *)(v2 + 8) = v44;
//             LODWORD(v44) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 + 12) = HIDWORD(v44);
//             v45 = (*(int (__thiscall **)(StructPlayer *))(v44 + 64))(v4);
//             *(_DWORD *)(v2 + 80) = v45;
//             LODWORD(v45) = v4->m_nAccountID;
//             *(_DWORD *)(v2 + 84) = HIDWORD(v45);
//             v45 = (signed int)v45;
//             *(_DWORD *)(v2 - 20) = v45;
//             *(_DWORD *)(v2 + 40) = LODWORD(v4->m_nGold.m_nGold);
//             *(_DWORD *)(v2 + 44) = HIDWORD(v4->m_nGold.m_nGold);
//             LODWORD(v45) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 - 16) = HIDWORD(v45);
//             v46 = (const char *)(*(int (__thiscall **)(StructPlayer *))(v45 + 60))(v4);
//             LOG::Log11N4S(
//             0x836u,
//             (const __int64 *)(v2 - 20),
//             (const __int64 *)(v2 + 80),
//             (const __int64 *)(v2 + 8),
//             (const __int64 *)(v2 - 52),
//             (const __int64 *)(v2 + 24),
//             (const __int64 *)(v2 - 100),
//             (const __int64 *)(v2 + 40),
//             (const __int64 *)(v2 - 36),
//             (const __int64 *)(v2 + 56),
//             (const __int64 *)(v2 - 68),
//             (const __int64 *)(v2 - 84),
//             v4->m_szAccountName,
//             -1,
//             v46,
//             -1,
//             (const char *)&unk_5F42BB,
//             0,
//             (const char *)&unk_5F42BB,
//             0);
//             v47 = (double)v4->m_fImmoralPoint.value;
//             *(_DWORD *)(v2 + 72) = LODWORD(v4->baseclass_0.m_nEXP);
//             *(_DWORD *)(v2 + 76) = HIDWORD(v4->baseclass_0.m_nEXP);
//             v48 = (unsigned __int64)(v47 / 10000.0);
//             *(_DWORD *)(v2 + 64) = v48;
//             LODWORD(v48) = v4->m_nChaos;
//             *(_DWORD *)(v2 + 68) = HIDWORD(v48);
//             v48 = (signed int)v48;
//             *(_DWORD *)(v2 + 48) = v48;
//             LODWORD(v48) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 + 52) = HIDWORD(v48);
//             v49 = (*(int (__thiscall **)(StructPlayer *))(v48 + 92))(v4);
//             *(_DWORD *)v2 = v49;
//             LODWORD(v49) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 + 4) = HIDWORD(v49);
//             v50 = (*(int (__thiscall **)(StructPlayer *))(v49 + 124))(v4);
//             *(_DWORD *)(v2 - 28) = v50;
//             LODWORD(v50) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 - 24) = HIDWORD(v50);
//             v51 = (*(int (__thiscall **)(StructPlayer *))(v50 + 96))(v4);
//             *(_DWORD *)(v2 - 44) = v51;
//             LODWORD(v51) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 - 40) = HIDWORD(v51);
//             v52 = (*(int (__thiscall **)(StructPlayer *))(v51 + 72))(v4);
//             *(_DWORD *)(v2 - 60) = v52;
//             LODWORD(v52) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 - 56) = HIDWORD(v52);
//             v53 = (*(int (__thiscall **)(StructPlayer *))(v52 + 64))(v4);
//             *(_DWORD *)(v2 - 76) = v53;
//             LODWORD(v53) = v4->m_nAccountID;
//             *(_DWORD *)(v2 - 72) = HIDWORD(v53);
//             v53 = (signed int)v53;
//             *(_DWORD *)(v2 - 92) = v53;
//             *(_DWORD *)(v2 + 32) = LODWORD(v4->m_nStorageGold.m_nGold);
//             *(_DWORD *)(v2 + 36) = HIDWORD(v4->m_nStorageGold.m_nGold);
//             *(_DWORD *)(v2 + 16) = LODWORD(v4->m_nGold.m_nGold);
//             *(_DWORD *)(v2 + 20) = HIDWORD(v4->m_nGold.m_nGold);
//             LODWORD(v53) = v4->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr;
//             *(_DWORD *)(v2 - 88) = HIDWORD(v53);
//             v54 = (const char *)(*(int (__thiscall **)(StructPlayer *))(v53 + 60))(v4);
//             LOG::Log11N4S(
//             0x837u,
//             (const __int64 *)(v2 - 92),
//             (const __int64 *)(v2 - 76),
//             (const __int64 *)(v2 - 60),
//             (const __int64 *)(v2 - 44),
//             (const __int64 *)(v2 - 28),
//             (const __int64 *)v2,
//             (const __int64 *)(v2 + 16),
//             (const __int64 *)(v2 + 32),
//             (const __int64 *)(v2 + 48),
//             (const __int64 *)(v2 + 64),
//             (const __int64 *)(v2 + 72),
//             v4->m_szAccountName,
//             -1,
//             v54,
//             -1,
//             (const char *)&unk_5F42BB,
//             0,
//             (const char *)&unk_5F42BB,
//             0);
//            v4->pConnection = 0;
            RappelzServer.Instance.DeleteObject(this);
//            ArcadiaAutoLock::_ArcadiaAutoLock((ArcadiaAutoLock *)(v2 - 120));
        }

        public void LogoutNowWithAccount(int nCallerIdx)
        {
//             int v2; // ebp@0
//             StructPlayer *v3; // esi@1
//             const char *v4; // edi@1
//             unsigned int v5; // eax@1
//             void *v6; // ebx@1
//             ArcadiaServer *v7; // eax@1
//             ArcadiaLock *v8; // eax@1
//             IStreamSocketConnection *v9; // eax@1
//             ILockVtbl *v10; // eax@7

            ConnectionTag tag = null;

            Player.UnRegisterAccount(this.m_szAccountName);
            uint cpt = this.GetContinuousPlayTime();
            AuthClientNetwork.Instance.SendLogoutToAuth(this.m_szAccountName, cpt, 2);

//            g_ConnectionTagLock.baseclass_0.vfptr->Lock(&g_ConnectionTagLock);

//            v8 = RappelzServer.Instance._LockObjectWithVisibleRange((v2 - 20), this);
//            ArcadiaAutoLock::ArcadiaAutoLock((v2 - 40),v8);
            if (this.Connection != null)
                tag = this.Connection.Tag;
  //          ArcadiaAutoLock::_ArcadiaAutoLock((v2 - 40));
            if (tag != null && tag.szAccountName.Length > 0 && tag.bAuthByAuthServer)
                tag.bAuthByAuthServer = false;

//            v10->UnLock(&g_ConnectionTagLock);
            this.LogoutNow(nCallerIdx);

        }

// Function       :   public void StructPlayer::OnConnectionClosed(struct _CONNECTION_TAG *)
        public bool IsLogin()
        {
            return m_bIsLogin;
        }
// Function       :   public void SetLastLogoutRequestedTime(const unsigned long &)
// Function       :   public const unsigned long GetLastLogoutRequestedTime()
        public int PartyId
        {
            get { return m_nPartyId; }
            set { m_nPartyId = value; }
        }
        // Function       :   public bool IsInParty()
// Function       :   public bool HasItemPriority()
// Function       :   public void SetItemPriority()
// Function       :   public void ReleaseItemPriority()
// Function       :   public bool StructPlayer::IsPartyInvitable(struct StructPlayer *)
        public int GuildId
        {
            get { return m_nGuildId; }
            set { m_nGuildId = value; }
        }

        public int GetGuildID()
        {
            return m_nGuildId;
        }

        public int PrevGuildId
        {
            get { return m_nPrevGuildId; }
            set { m_nPrevGuildId = value; }
        }

        public int GetPrevGuildID()
        {
            return m_nPrevGuildId;
        }

// Function       :   public bool IsInGuild()
// Function       :   public bool StructPlayer::IsGuildInvitable(struct StructPlayer *)

        public long GetGuildBlockTime()
        {
            long result;
            if (this.m_tGuildBlockTime <= Globals.GetUnixTimestampInt64())
                result = 0;
            else
                result = this.m_tGuildBlockTime;
            return result;
        }
// Function       :   public void SetGuildBlockTime(__int64)
// Function       :   public void StructPlayer::AddFriend(const char *)
// Function       :   public bool StructPlayer::addFriend(const char *)
// Function       :   public void StructPlayer::AddFriendOf(const char *)
// Function       :   public void StructPlayer::AddDenial(const char *)
// Function       :   public bool StructPlayer::addDenial(const char *)
// Function       :   public void StructPlayer::AddDenialOf(const char *)

        public void DelFriend(string szName)
        {
            this.DBQuery(new DB_DeleteFriend(this.GetName(), szName,false,this));
        }

        public bool delFriend(string szName)
        {
            //            s_FriendsLock.baseclass_0.vfptr->Lock(&s_FriendsLock);

            for (int i = this.m_vFriend.Count - 1; i >= 0; --i)
            {
                if (this.m_vFriend[i].ToLower() == szName.ToLower())
                {
                    this.m_vFriend.RemoveAt(i);
                    return true;
                }
            }
            //            v9->UnLock(&s_FriendsLock);
            return false;
        }

        public void DelFriendOf(string szName)
        {
            //            s_FriendsLock.baseclass_0.vfptr->Lock(&s_FriendsLock);

            for (int i = this.m_vFriendOf.Count - 1; i >= 0; --i)
            {
                if (this.m_vFriendOf[i].ToLower() == szName.ToLower())
                {
                    this.m_vFriendOf.RemoveAt(i);
                }
            }
            //            v9->UnLock(&s_FriendsLock);

        }

        public void DelDenial(string szName)
        {
            this.DBQuery(new DB_DeleteFriend(this.GetName(),szName,true,this));
        }

        public bool delDenial(string szName)
        {
            //            s_FriendsLock.baseclass_0.vfptr->Lock(&s_FriendsLock);

            for (int i = this.m_vDenial.Count - 1; i >= 0; --i)
            {
                if (this.m_vDenial[i].ToLower() == szName.ToLower())
                {
                    this.m_vDenial.RemoveAt(i);
                    return true;
                }
            }
            //            v9->UnLock(&s_FriendsLock);
            return false;
        }

        public void DelDenialOf(string szName)
        {
//            s_FriendsLock.baseclass_0.vfptr->Lock(&s_FriendsLock);

            for(int i = this.m_vDenialOf.Count-1; i >= 0; --i)
            {
                if(this.m_vDenialOf[i].ToLower() == szName.ToLower())
                {
                    this.m_vDenialOf.RemoveAt(i);
                }
            }
//            v9->UnLock(&s_FriendsLock);
        }

// Function       :   public bool StructPlayer::IsFriend(const char *)

        public bool IsFriendOf(string szName)
        {
//            s_FriendsLock.baseclass_0.vfptr->Lock(&s_FriendsLock);

            for(int i = this.m_vFriendOf.Count-1; i >= 0; --i)
            {
                if(this.m_vFriendOf[i].ToLower() == szName.ToLower())
                {
                    return true;
                }
            }
//            v9->UnLock(&s_FriendsLock);
            return false;   
        }

        public bool IsDenial(string szName)
        {
            return false;
        }
// Function       :   public bool IsDenialOf(const char *)
// Function       :   public const unsigned int GetFriendCount()
// Function       :   public const unsigned int GetFriendOfCount()
// Function       :   public const unsigned int GetDenialCount()
// Function       :   public const unsigned int GetDenialOfCount()
// UserDefinedType:   FriendDenialFunctor
// VTable         :     , Type:  *
// Function       :     public const bool operator()(class std::basic_string<char,std::char_traits<char>,std::allocator<char> > &)
// Function       :     public void FriendDenialFunctor(const struct StructPlayer::FriendDenialFunctor &)
// Function       :     public void FriendDenialFunctor()
// Function       :     public struct StructPlayer::FriendDenialFunctor & operator=(const struct StructPlayer::FriendDenialFunctor &)
// Function       :   public const unsigned int StructPlayer::DoEachFriend(struct StructPlayer::FriendDenialFunctor &)
// Function       :   public const unsigned int StructPlayer::DoEachFriendOf(struct StructPlayer::FriendDenialFunctor &)
// Function       :   public const unsigned int StructPlayer::DoEachDenial(struct StructPlayer::FriendDenialFunctor &)
// Function       :   public const unsigned int DoEachDenialOf(struct StructPlayer::FriendDenialFunctor &)
        public string GetFlag(string szKey)
        {
            lock (m_hsValue)
            {
                if (m_hsValue.ContainsKey(szKey))
                {
                    return m_hsValue[szKey];

                }
            }
            return "<null>";
        }
        
        public bool RemoveFlag(string szKey)
        {
            lock (m_hsValue)
            {
                if (m_hsValue.ContainsKey(szKey))
                {
                    m_hsValue.Remove(szKey);
                    return true;
                }
            }
            return false;
        }

        public bool IsExistFlag(string szKey)
        {
            lock (m_hsValue)
            {
                if (m_hsValue.ContainsKey(szKey))
                    return true;
            }
            return false;
        }

        public void SetFlag(string szKey, string szData)
        {
            lock(m_hsValue)
            {
                if(m_hsValue.ContainsKey(szKey))
                    m_hsValue[szKey] = szData;
                else
                    m_hsValue.Add(szKey,szData);
            }
        }

        public void EnumFlag(ref string strValueList)
        {
            strValueList = "";
            foreach (KeyValuePair<string,string> kvp in this.m_hsValue)
            {
                strValueList += kvp.Key;
                strValueList += ":";
                strValueList += kvp.Value;
                strValueList += "\n";
            }
        }

        public enum BoothStatus : int
        {
            IsNotBooth = 0,
            SellBooth = 1,
            BuyBooth = 2,
        }
// Enum           :   BOOTH_STATUS, Type: int
// Data           :     constant 0x0, Constant, Type: int, IS_NOT_BOOTH
// Data           :     constant 0x1, Constant, Type: int, SELL_BOOTH
// Data           :     constant 0x2, Constant, Type: int, BUY_BOOTH
// UserDefinedType:   BOOTH_OPEN_ITEM_INFO
// Data           :     this+0x0, Member, Type: unsigned int, handle
// Data           :     this+0x4, Member, Type: int, cnt
// Data           :     this+0x8, Member, Type: __int64, gold
// UserDefinedType:   BOOTH_ITEM_INFO
// Data           :     this+0x0, Member, Type: struct StructItem *, pItem
// Data           :     this+0x4, Member, Type: int, cnt
// Data           :     this+0x8, Member, Type: __int64, gold
// UserDefinedType:   BOOTH_ITEM_BUY_INFO
// Data           :     this+0x0, Member, Type: int, nIdx
// Data           :     this+0x4, Member, Type: int, nCount
// Function       :   public bool StructPlayer::OpenBooth(const char *, const class std::vector<StructPlayer::BOOTH_OPEN_ITEM_INFO,std::allocator<StructPlayer::BOOTH_OPEN_ITEM_INFO> > &, bool)
// Function       :   public bool StructPlayer::CloseBooth()
// Function       :   public enum StructPlayer::BOOTH_STATUS GetBoothStatus()
// Function       :   public const char * StructPlayer::GetBoothName()
// Function       :   public const class std::vector<StructPlayer::BOOTH_ITEM_INFO,std::allocator<StructPlayer::BOOTH_ITEM_INFO> > & StructPlayer::GetBoothItemList()
// Function       :   public void StructPlayer::WatchBooth(struct StructPlayer *)
// Function       :   public void StructPlayer::StopWatchBooth()
// Function       :   public bool IsBoothWatching()
// Function       :   public bool StructPlayer::BuyFromBooth(struct StructPlayer *, class std::vector<StructPlayer::BOOTH_ITEM_BUY_INFO,std::allocator<StructPlayer::BOOTH_ITEM_BUY_INFO> > &)
// Function       :   public bool StructPlayer::SellToBooth(struct StructPlayer *, unsigned int, int, const __int64 &)
// Function       :   public static class XCriticalSection * StructPlayer::GetBoothLock()
// Function       :   public bool IsBoothOpen()
// Function       :   public bool StructPlayer::IsActable()
// Function       :   public bool StructPlayer::IsMovable()
// Function       :   public bool StructPlayer::IsAttackable()
// Function       :   public const unsigned short StructPlayer::IsBoothOpenable()
// Function       :   public bool StructPlayer::IsMountable()

        public bool IsItemPickable()
        {
            return this.IsActable() && !this.IsSitDown() && !this.IsUsingSkill() && this.m_hEnemy == 0;
        }

        public bool IsSitdownable()
        {
            return this.IsActable()
                && !this.IsSitDown()
                && !this.IsUsingSkill()
                && this.m_nRideIdx == 0
                && this.m_nRidingStateUid == 0;

        }

        public override bool IsItemUseable()
        {
            bool result;

            if (this.m_BoothStatus != BoothStatus.IsNotBooth)
                result = false;
            else
                result = base.IsItemUseable();
            return result;
        }
// Function       :   public bool StructPlayer::IsItemWearable()
// Function       :   public unsigned int GetTamingTarget()
// Function       :   public void SetTamingTarget(unsigned int)
// Function       :   public void SitDown()
// Function       :   public void StandUp()

        public override bool IsSitDown()
        {
            return m_bIsSitDown;
        }
// Function       :   public void SetBattleModeOn()
// Function       :   public void SetBattleModeOff()

        public override bool IsBattleMode()
        {
            return m_bIsBattleMode;
        }

// Function       :   public bool HasRidingState()
// Function       :   public bool IsRiding()

        public uint GetRideHandle()
        {
            return 0;
        }

        public Summon GetRideObject()
        {
            return null;
        }
// Function       :   public int StructPlayer::GetUnMountProbabilityOnDamage()
// Function       :   public int StructPlayer::GetUnMountProbabilityOnCriticalDamage()
// Enum           :   <unnamed-tag>, Type: int
// Data           :     constant 0x0, Constant, Type: int, UNMOUNT_NORMAL
// Data           :     constant 0x1, Constant, Type: int, UNMOUNT_FALL
// Data           :     constant 0x2, Constant, Type: int, UNMOUNT_UNSUMMON
// Function       :   public void StructPlayer::MountSummon(unsigned int)

        public void UnMount(byte flag)
        {
/*
            StructPlayer *v2; // esi@1
            void *v3; // eax@4
            bool v4; // zf@4
            unsigned int v5; // edi@6
            ArcadiaServer *v6; // eax@6
            ArObject *v7; // ST08_4@6
            ArcadiaServer *v8; // eax@6
            double v9; // st7@7
            char v10; // ST1C_1@7
            unsigned int v11; // ST14_4@7
            ArcadiaServer *v12; // eax@7
            StructCreature *v13; // ecx@7
            int v14; // edi@10
            unsigned int v15; // eax@11
            TS_SC_UNMOUNT_SUMMON msg; // [sp+Ch] [bp-2Ch]@7
            ArPosition pos; // [sp+1Ch] [bp-1Ch]@6
            void *pSummon; // [sp+2Ch] [bp-Ch]@4
            char layer[4]; // [sp+30h] [bp-8h]@7
            float v20; // [sp+34h] [bp-4h]@7

            v2 = this;
            if ( this->m_nRidingStateUid )
            {
                StructCreature::RemoveState(&this->baseclass_0, this->m_nRidingStateUid);
            }
            else
            {
                if ( !this->m_nRideIdx )
                    return;
                v3 = StructPlayer::GetRideObject(this);
                v4 = v2->baseclass_0.baseclass_0.baseclass_0.mv.bIsMoving == 0;
                pSummon = v3;
                if ( !v4 && v2->baseclass_0.baseclass_0.baseclass_0.bIsInWorld )
                {
                    v5 = GetArTime();
                    ArObject::GetCurrentPosition(&v2->baseclass_0.baseclass_0.baseclass_0, &pos, v5);
                    v6 = ArcadiaServer::Instance();
                    ArcadiaServer::SetMove(v6, &v2->baseclass_0.baseclass_0.baseclass_0, &pos, &pos, 0, 1, v5, 1);
                    v7 = StructPlayer::GetRideObject(v2);
                    v8 = ArcadiaServer::Instance();
                    ArcadiaServer::SetMove(v8, v7, &pos, &pos, 0, 1, v5, 0);
                }
                TS_SC_UNMOUNT_SUMMON::TS_SC_UNMOUNT_SUMMON(&msg);
                msg.handle = v2->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr->GetHandle(v2);
                msg.summon_handle = StructPlayer::GetRideHandle(v2);
                v20 = g_nRegionSize;
                msg.flag = flag;
                v9 = v2->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.y / v20;
                layer[0] = v2->baseclass_0.baseclass_0.baseclass_0.layer;
                v10 = layer[0];
                v11 = (v2->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.x / v20);
                v12 = ArcadiaServer::Instance();
                ArcadiaServer::Broadcast(v12, v11, v9, v10, &msg);
                v13 = pSummon;
                v4 = pSummon == 0;
                v2->m_nRideIdx = 0;
                if ( !v4 )
                    StructCreature::CalculateStat(v13);
            }
            if ( flag == 1 )
            {
                v14 = v2->baseclass_0.m_nHP;
                if ( v14 )
                {
                    StructCreature::AddHP(&v2->baseclass_0, (0.0 - v2->baseclass_0.m_nMaxHP * 0.05000000074505806));
                    BroadcastHPMPMsg(&v2->baseclass_0, v2->baseclass_0.m_nHP - v14, 0, 0);
                    v15 = GetArTime();
                    StructCreature::AddState(&v2->baseclass_0, 0, FALL_FROM_SUMMON, 0, 1, v15, v15 + 300, 0, 0, &unk_5F42BB);
                }
            }
*/
        }


        public bool IsPendWarp()
        {
            return this.m_nPendWarpX >= 0.0 && this.m_nPendWarpY >= 0.0;
        }

        public void ProcessWarp()
        {
// .text:004537BE _lock           = ArcadiaAutoLock ptr -24h
// .text:004537BE __lock          = ArcadiaLock ptr  3Ch
// .text:004537BE min_rx_value    = dword ptr  48h
            int max_rx;//          = dword ptr  4Ch
            int max_ry;
            int min_rx;
            int min_ry;
            int rx;
            int ry;
            int min_rx_value;
            int max_rx_value;
            int min_ry_value;
            int max_ry_value;

// .text:004537BE min_rx          = dword ptr  50h
// .text:004537BE it              = std::_Vector_iterator<StructSummon *,std::allocator<StructSummon *> > ptr  58h
// .text:004537BE nWarpLayer      = byte ptr  63h
// .text:004537BE min_ry          = dword ptr  68h
// .text:004537BE rx              = dword ptr  6Ch
// .text:004537BE ry              = dword ptr  70h
// .text:004537BE max_ry          = dword ptr  74h
// 
// Data           :   ebp Relative, [00000050], Local, Type: unsigned int, min_rx
// Data           :   ebp Relative, [00000070], Local, Type: unsigned int, ry
// Data           :   ebp Relative, [0000004C], Local, Type: unsigned int, max_rx
// Data           :   ebp Relative, [0000003C], Local, Type: struct ArcadiaLock, __lock
// Data           :   ebp Relative, [00000048], Local, Type: unsigned int, min_rx_value
// Data           :   ebp Relative, [00000068], Local, Type: unsigned int, min_ry
// Data           :   ebp Relative, [FFFFFFDC], Local, Type: struct ArcadiaAutoLock, _lock
            int nHuntaholicID;// Data           :   ebp Relative, [00000074], Local, Type: int, nHuntaholicID
// Data           :   ebp Relative, [00000074], Local, Type: unsigned int, max_ry
// Data           :   ebp Relative, [0000006C], Local, Type: unsigned int, rx
// Data           :   ebp Relative, [FFFFFFC8], Local, Type: struct ArcadiaAutoLock, _lock
// Data           :   ebp Relative, [00000063], Local, Type: unsigned char, nWarpLayer
// Data           :   ebp Relative, [FFFFFFB4], Local, Type: struct ArcadiaAutoLock, _lock
// Data           :   ebp Relative, [00000058], Local, Type: class std::_Vector_iterator<StructSummon *,std::allocator<StructSummon *> >, it
// Data           :   ebp Relative, [00000044], Local, Type: unsigned int, min_rx_value
            RLock rl;
            AutoLock al;
            ArPosition wp;
            ushort res;

            if (this.m_nPendWarpX >= 0.0f && this.m_nPendWarpY >= 0.0f && GameContent.g_nMapWidth >= this.m_nPendWarpX && GameContent.g_nMapHeight >= this.m_nPendWarpY)
            {
                nHuntaholicID = HuntaholicManager.Instance.GetHuntaholicID(this.mv);
                if (nHuntaholicID != 0)
                {
                    wp = new ArPosition(this.m_nPendWarpX, this.m_nPendWarpY,0);
                    if ( HuntaholicManager.Instance.GetHuntaholicID(wp) != nHuntaholicID)
                    {
                        rl = RappelzServer.Instance._LockObjectWithVisibleRange(this);
                        al = new AutoLock(rl.handle);
                        this.RemoveAllStateByQuittingHuntaholic();
//                        ArcadiaAutoLock::_ArcadiaAutoLock((v1 - 56));
                        if (this.m_nPartyId != 0)
                        {
                            if (HuntaholicManager.Instance.IsHuntaholicLobby(this.mv))
                            {
                                res = HuntaholicManager.Instance.LeaveInstanceDungeon(nHuntaholicID, this);
                                if (res != 0 && this.m_nPartyId != 0)
                                {
                                    Globals.Log.Error("StructPlayer::ProcessWarp(): LeaveInstanceDungeon failed(ErrorCode: {0})", res);
                                    this.m_nPendWarpY = -1.0f;
                                    this.m_nPendWarpX = -1.0f;
                                    this.m_nPendWarpLayer = 0;
                                    return;
                                }
                            }
                            else
                            {
//                                 v18 = this.m_nPendWarpLayer;
//                                 *(v1 + 84) = this.m_nPendWarpX;
//                                 *(v1 + 104) = this.m_nPendWarpY;

                                res = HuntaholicManager.Instance.QuitHunting(nHuntaholicID, this, false, -1);

//                                 this.m_nPendWarpX = *(v1 + 84);
//                                 this.m_nPendWarpY = *(v1 + 104);
//                                 this.m_nPendWarpLayer = v22;
                                if (res != 0 && this.m_nPartyId != 0)
                                {
                                    Globals.Log.Error("StructPlayer::ProcessWarp(): QuitHunting failed(ErrorCode: {0})", res);
                                    this.m_nPendWarpY = -1.0f;
                                    this.m_nPendWarpX = -1.0f;
                                    this.m_nPendWarpLayer = 0;
                                    return;
                                }
                            }
                            Messages.SendResult(this.Connection, (ushort)0xFA5u, 0, 0);
                        }
                    }
                }
                min_rx = -1;
                min_ry = -1;
                max_rx = 0;
                max_ry = 0;
               
                rl = RappelzServer.Instance._LockObjectWithVisibleRange(this);
                al = new AutoLock(rl.handle);

                foreach (Summon s in this.m_vSummonList)
                {
                    if (s.m_bIsSummoned && s.bIsInWorld)
                    {
                        if ((int)((s.mv.x + 108) / GameContent.g_nRegionSize) < min_rx)
                            min_rx = (int)((s.mv.x + 108) / GameContent.g_nRegionSize);
                        if ((int)((s.mv.x + 108) / GameContent.g_nRegionSize) > max_rx)
                            max_rx = (int)((s.mv.x + 108) / GameContent.g_nRegionSize);
                        if ((int)((s.mv.y + 112) / GameContent.g_nRegionSize) < min_ry)
                            min_ry = (int)((s.mv.y + 112) / GameContent.g_nRegionSize);
                        if ((int)((s.mv.y + 112) / GameContent.g_nRegionSize) > min_ry)
                            max_ry = (int)((s.mv.y + 112) / GameContent.g_nRegionSize);

                    }
                }
//                ArcadiaAutoLock::_ArcadiaAutoLock((v1 - 76));

                rx = (int)(this.mv.x / GameContent.g_nRegionSize);
                min_rx_value = (int)(this.m_nPendWarpX / GameContent.g_nRegionSize);
                if (min_rx_value >= rx)
                    min_rx_value = rx;

                max_rx_value = (int)(this.m_nPendWarpX / GameContent.g_nRegionSize);
                if (max_rx_value < rx)
                    max_rx_value = rx;

                ry = (int)(this.mv.y / GameContent.g_nRegionSize);
                min_ry_value = (int)(this.m_nPendWarpY / GameContent.g_nRegionSize);
                if (min_ry_value >= ry)
                    min_ry_value = ry;

                max_ry_value = (int)(this.m_nPendWarpY / GameContent.g_nRegionSize);
                if (max_ry_value < ry)
                    max_ry_value = ry;

                rl = RappelzServer.Instance._LockArea((uint)min_rx_value, (uint)min_ry_value, (uint)max_rx_value, (uint)max_ry_value);
/*
                while ( 1 )
                {
                    if (rx == (this.mv.x / GameContent.g_nRegionSize) )
                    {
                        if (ry == (this.mv.y / GameContent.g_nRegionSize) )
                            break;
                    }

                    RappelzServer.Instance.UnLock(rl);
                    *(v1 + 100) = GameContent.g_nRegionSize;
                    v47 = GameContent.g_nRegionSize;
                    v48 = v3->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.y;
                    *(v1 + 108) = (v3->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.x / GameContent.g_nRegionSize);
                    v49 = (v48 / GameContent.g_nRegionSize);
                    v50 = v3->m_nPendWarpX;
                    *(v1 + 112) = v49;
                    v51 = (v50 / GameContent.g_nRegionSize);
                    v33 = v51 < *(v1 + 108);
                    *(v1 + 68) = v51;
                    v52 = v1 + 68;
                    if ( !v33 )
                        v52 = v1 + 108;
                    if (min_rx < *v52 )
                        v52 = min_rx;
                    v53 = *v52;
                    v33 = *(v1 + 108) < v51;
                    *(v1 + 64) = v51;
                    *(v1 + 68) = v53;
                    v54 = v1 + 64;
                    if ( !v33 )
                        v54 = v1 + 108;
                    if ( *v54 < max_rx)
                        v54 = max_rx;
                    v55 = *v54;
                    v56 = (v3->m_nPendWarpY / GameContent.g_nRegionSize);
                    v33 = v56 < *(v1 + 112);
                    *(v1 + 84) = v56;
                    v57 = v1 + 84;
                    if ( !v33 )
                        v57 = v1 + 112;
                    if ( *(v1 + 104) < *v57 )
                        v57 = v1 + 104;
                    v33 = *(v1 + 112) < v56;
                    v58 = *v57;
                    *(v1 + 56) = v56;
                    v59 = v1 + 56;
                    if ( !v33 )
                        v59 = v1 + 112;
                    if ( *v59 < max_ry)
                        v59 = max_ry;
                    v60 = *v59;
                    v61 = v58;
                    v62 = *(v1 + 68);

                    rl = RappelzServer.Instance._LockArea(v62,v61,v55,v60);
                }
*/
                al = new AutoLock(rl.handle);

                if (this.bIsInWorld)
                {
                    GameContent.WarpBegin(this);
                    GameContent.WarpEnd(this, new ArPosition(this.m_nPendWarpX, this.m_nPendWarpY,0), this.m_nPendWarpLayer);
                    this.m_nPendWarpY = -1.0f;
                    this.m_nPendWarpX = -1.0f;
                    this.m_nPendWarpLayer = 0;
                    this.m_nWarpEndTime = Globals.GetArTime();
                    this.ClearDialogMenu();
                }
//                ArcadiaAutoLock::_ArcadiaAutoLock((v1 - 36));
            }


        }
// Function       :   public int GetStamina()
        public void AddStamina(int nStamina)
        {
            int stam_add = nStamina;
            int old_stamina = m_nStamina;
            if ( nStamina > 0 )
            {
                if (old_stamina + nStamina > m_nMaxStamina)
                {
                    if (m_nMaxStamina <= old_stamina )
                        stam_add = 0;
                    else
                        stam_add = m_nMaxStamina - old_stamina;
                }
            }
            if (stam_add != 0)
            {
                m_nStamina += stam_add;
                if (m_nStamina < 0)
                    m_nStamina = 0;

                if (m_nStamina != old_stamina)
                {
                    Messages.SendPropertyMessage(this, m_hHandle, "stamina", m_nStamina);
                }
            }

        }

        public int GetStaminaRegenRate()
        {
            int result = 30;

            if (!m_bUsingTent)
            {
                if (IsInTown())
                    result = GetCondition() != 0 ? 100 : 110;
            }
            else
            {
                result = 120;
            }

            if (m_bIsGaiaMember )
                result *= 2;

            result += m_nStaminaRegenBonus;
            if (m_nStaminaRegenRate != result )
            {
                m_nStaminaRegenRate = result;
                Messages.SendPropertyMessage(this, this.m_hHandle, "stamina_regen", result);
            }
            return result;

        }

        public Player.ConditionInfo GetCondition()
        {
            ConditionInfo result;

            if (m_nStamina >= 10000)
                result = (m_nStamina < 130000) ? ConditionInfo.ConditionAverage : ConditionInfo.ConditionGood;
            else
                result = ConditionInfo.ConditionBad;
            return result;

        }
// Function       :   public int GetLogoutDuration()
// Function       :   public void SetLogoutDuration(int)
        public bool PutOnBelt(int pos, Item item)
        {

            if (pos < m_nBeltSlotMax)
            {
                if (m_aBeltSlotCard[pos] == null )
                {
                    if ((item.m_pItemBase.nGroup == 13 && (item.m_Instance.Flag & 0x80000000) != 0) || (item.m_pItemBase.nGroup == 140))
                    {
                        int i = 0;

                        // first we need to make sure that the pet isn't in formation
                        for(i = 0; i < 6; ++i)
                        {
                            if(this.m_aBindSummonCard[i] != null && item.IsSameObject(this.m_aBindSummonCard[i]))
                                return false;
                        }

                        // now let's see if we have it on our belt already
                        for(i = 0; i < 6; ++i)
                        {
                            if(this.m_aBeltSlotCard[i] != null && item.IsSameObject(this.m_aBeltSlotCard[i]))
                                return false;
                        }

                        m_aBeltSlotCard[pos] = item;
                        return true;
                    }
                }
            }

            return false;
        }

        public void PutOffBelt(int pos)
        {
            if (pos < 6)
                this.m_aBeltSlotCard[pos] = null;
        }

// Function       :   public int GetLocationId()
        public void ChangeLocation(float x, float y, bool bByRequest, bool bBroadcast)
        {
// Data           :   ebp Relative, [-60], Local, Type: struct ArPosition, pos
// Data           :   ebp Relative, [-44], Local, Type: struct ArPosition, client_pos
// Data           :   ebp Relative, [-28], Local, Type: struct TS_SC_CHANGE_LOCATION, msg
// Data           :   ebp Relative, [-80], Local, Type: struct ArcadiaAutoLock, _lock

            
//             ArcadiaAutoLock::ArcadiaAutoLock(_lock);
//             if (bByRequest)
//             {
//                 v10 = Rappelz.Instance._LockObjectWithVisibleRange(bByRequest, this);
//                 ArcadiaAutoLock::set(_lock, v10, "??", 0);
//             }
            ArPosition client_pos = new ArPosition(x,y,0.0f);
            uint ct = Globals.GetArTime();
            ArPosition pos = this.GetCurrentPosition(ct);
            if (client_pos.GetDistance(pos) < 120.0f)
            {
                pos.x = client_pos.x;
                pos.y = client_pos.y;
                pos.z = client_pos.z;
                pos.face = client_pos.face;
            }
           
            int nl = GameContent.GetLocationId(pos.x,pos.y);
            PacketOut po = new PacketOut((ushort)ClientOutPackets.ChangeLocation);
            po.WriteInt32(this.m_nWorldLocationId);
            po.WriteInt32(nl);
            this.Connection.SendTCP(po);
            ChannelManager.GetChannelType(this.m_nWorldLocationId);

            if (this.m_nWorldLocationId != nl)
            {
                if (this.m_nWorldLocationId != 0)
                {
                    WorldLocationManager.Instance.RemoveFromLocation(this);
                    this.m_WorldLocation = null;
                }
                if (nl != 0)
                {
                    this.m_WorldLocation = WorldLocationManager.Instance.AddToLocation((uint)nl,this);
                    if ( (this.m_nTurnOnPkModeTime != 08 || this.m_bIsPK && this.m_nTurnOffPkModeTime == 0) && !this.IsInPKField())
                        this.TurnOffPkMode(false);
                    if (bBroadcast && this.IsDungeonOriginalOwner())
                        Messages.BroadcastStatusMessage(this);
                    if (this.m_nCompeteID != 0 && !this.isInLocationType(2) && !this.isInLocationType(5))
                        CompeteManager.Instance.RetireCompeteWithPlayer(this, CompeteEndType.EnteringSafetyZone);
                }
                this.m_nWorldLocationId = nl;
            }
//            ArcadiaAutoLock::_ArcadiaAutoLock((v5 - 80));
        }

        public bool IsInTown()
        {
            return isInLocationType(1) || isInLocationType(10);
        }
// Function       :   public bool StructPlayer::IsInField()

        public bool IsInBattleField()
        {
            return this.isInLocationType(5);
        }

        public bool IsInEventmap()
        {
            return this.isInLocationType(7);
        }
// Function       :   public bool IsUsingTent()

        public bool IsInSiegeOrRaidDungeon()
        {
            return DungeonManager.Instance.GetDungeonID(this.mv.x, this.mv.y) != 0 && this.m_layer > 1;
        }

        public bool IsInSiegeDungeon()
        {
            WorldLocation l = this.m_WorldLocation;
            if (l == null || l.location_type != 4 || this.m_layer != 1)
                return false;
            return true;
        }

        public bool IsInDungeon()
        {
            return false;
        }
// Function       :   public bool IsGaiaMember()
// Function       :   public unsigned long GetGaiaMemberRemainTime()
// Function       :   public void StructPlayer::SetGaiaMemberRemainTime(unsigned long)
// Function       :   public bool IsPKOn()
// Function       :   public void SetPKOn()
// Function       :   public void SetPKOff()
// Function       :   public bool IsPKOning()
// Function       :   public bool IsPKOffing()
// Function       :   public const class c_fixed<10000> & GetImmoralPoint()

        public void SetImmoralPoint(float ip)
        {
            if (!this.IsInSiegeOrRaidDungeon())
            {
                this.m_fImmoralPoint = ip;
                Messages.SendPropertyMessage(this, this.m_hHandle, "immoral", (long) this.m_fImmoralPoint);
            }
        }
// Function       :   public int GetPKC()
// Function       :   public void StructPlayer::IncPKC()
// Function       :   public int GetDKC()
// Function       :   public void StructPlayer::IncDKC()
// Function       :   public bool IsBloodyCharacter()
// Function       :   public bool IsDemoniacCharacter()

        public bool IsDungeonOriginalOwner()
        {
            int gid = PartyManager.Instance.GetAttackTeamGuildID(this.m_nPartyId);
            return gid != 0 && IsInSiegeDungeon() && gid == DungeonManager.Instance.GetOriginalOwnGuildID(DungeonManager.Instance.GetDungeonID(mv.x,mv.y));
        }
// Function       :   public bool StructPlayer::IsDungeonOriginalSieger()

        public bool IsInSecroute()
        {
            return this.m_nWorldLocationId == 130100 || this.m_nWorldLocationId == 130101 || this.m_nWorldLocationId == 130107;
        }

        public override bool IsEnemy(Creature pTarget, bool bIncludeHiding)
        {
            return base.IsEnemy(pTarget, bIncludeHiding);
        }
// Function       :   public bool StructPlayer::IsAlly(struct StructCreature *)

        public bool IsInPKField()
        {
            WorldLocation l = this.m_WorldLocation;
            return l == null || (l.location_type != 1) && l.location_type != 3 && l.location_type != 5 && l.location_type != 7 && l.location_type != 8 && l.location_type != 9 && l.location_type != 10;
        }
// Function       :   public bool StructPlayer::TurnOnPkMode(const bool)

        public bool TurnOffPkMode(bool bImmediateOff)
        {
            uint ct = Globals.GetArTime();
            if (this.m_nTurnOnPkModeTime <= ct)
            {
                if (this.m_nTurnOffPkModeTime > ct)
                    return false;
                if (!bImmediateOff )
                    ct += 3000;
                this.m_nTurnOffPkModeTime = ct;
            }
            else
            {
                this.m_nTurnOnPkModeTime = 0;
            }
            return true;
        }

        public void UpdateQuestStatusByItemUpgrade()
        {
            List<Quest> vQuestList = new List<Quest>();

            this.m_QuestManager.GetRelatedQuest(vQuestList, 64);
            foreach (Quest q in vQuestList)
            {
                for(int i = 0; i < 6; i += 2)
                {
                    int level = q.GetValue(i+1);
                    if (level > 0)
                    {
                        int id = q.GetValue(i);
                        if (id < 24)
                        {
                            Item item = this.GetWornItem((ItemBase.ItemWearType)id);
                            if (item != null)
                            {
                                int qv = q.GetValue((2 * i) + 1);
                                if (level > qv)
                                    level = qv;
                                q.UpdateStatus(i/2, level);

                            }
                            else
                            {
                                q.UpdateStatus(i/2, 0);
                            }
                        }
                    }
                }
            }

        }

        public void UpdateQuestStatusByScript(int code, int idx, int val)
        {
            Quest q = this.m_QuestManager.FindQuest(code);
            if (q == null)
                return;
            q.UpdateStatus(idx, val);
        }


        public ArPosition GetLastTownPosition()
        {
            ArPosition result = new ArPosition();


            result.x = Marshal.ToSingle(this.GetFlag("rx"));
            result.y = Marshal.ToSingle(this.GetFlag("ry"));

            if ( 0.0f == result.x || 0.0f == result.y )
            {
                switch(this.GetRace())
                {
                    case 0:
                        result.x = (Globals.GetRandomInt32(0, 100) + 6625);
                        result.y = (Globals.GetRandomInt32(0, 100) + 6980);
                        break;
                    case 1:
                        result.x = (Globals.GetRandomInt32(0, 100) + 116799);
                        result.y = (Globals.GetRandomInt32(0, 100) + 58205);
                        break;
                    case 2:
                        result.x = (Globals.GetRandomInt32(0, 100) + 153513);
                        result.y = (Globals.GetRandomInt32(0, 100) + 77203);
                        break;
                }
            }
            return result;
        }
// Function       :   public void StructPlayer::GetLastHuntaholicEnteredPosition(struct ArPosition *)

        public void OpenStorage()
        {
            if (!this.IsUsingSkill())
            {
                if (this.m_bIsStorageRequested)
                {
                    if (this.m_bIsStorageRequested)
                    {
                        foreach (Item item in this.m_Storage.m_vList)
                        {
                            Messages.SendItemMessage(this, item);
                        }
                        this.openStorage();

                        Messages.SendPropertyMessage(this, this.m_hHandle, "storage_gold", this.m_nStorageGold);
                    }
                }
                else
                {
                    bool isLoaded = this.m_bIsStorageLoaded;
                    this.m_bIsStorageRequested = true;
                    this.m_bIsStorageLoaded = false;
                    this.DBQuery(new DB_ReadStorageList(this, isLoaded));
                }
            }

        }
// Function       :   public void SetContactNPCHandle(unsigned int)
// Function       :   public unsigned int GetContactNPCHandle()
// Function       :   public void SetNonNPCDialog(bool)
// Function       :   public bool IsNonNPCDialog()

        public void SetDialogTitle(string szString, int type)
        {
            if (szString != null)
            {
                this.m_nDialogType = type;
                if (type != 0)
                    this.m_bNonNPCDialog = true;
                this.m_strDialogTitle = szString;
                this.m_strDialogMenu = "";
                this.m_strSpecialDialogMenu = "";
            }
        }

// Function       :   public class std::basic_string<char,std::char_traits<char>,std::allocator<char> > GetDialogTitle()

        public void SetDialogText(string szString)
        {
            if (szString != null)
            {
                this.m_strDialogText += szString;
                this.m_strDialogMenu = "";
                this.m_strSpecialDialogMenu = "";
            }
        }

        public void ClearDialogMenu()
        {
            this.m_strDialogMenu = "";
        }

        public void SetSpecialDialogMenu(string szString)
        {
            this.m_strSpecialDialogMenu = szString;
        }

        public bool IsSpecialDialogMenu(string szTrigger)
        {
            return this.m_strSpecialDialogMenu.Contains(szTrigger);
        }

        public void ClearSpecialDialogMenu()
        {
            this.m_strSpecialDialogMenu = "";
        }
// Function       :   public void StructPlayer::SetFixedDialogTrigger(const char *)

        public bool IsFixedDialogTrigger(string szTrigger)
        {
            return this.m_strFixedDialogTrigger.Contains(szTrigger);
        }

        public void ClearFixedDialogTrigger()
        {
            this.m_strFixedDialogTrigger = "";
        }

        public void AddDialogMenu(string szString, string szTrigger)
        {
            if (szString != null && szTrigger != null)
            {
                if (!szString.Contains('\t') && !szTrigger.Contains('\t'))
                {
                    this.m_strDialogMenu += "\t";
                    this.m_strDialogMenu += szString;
                    this.m_strDialogMenu += "\t";
                    this.m_strDialogMenu += String.IsNullOrEmpty(szTrigger) ? "0" : szTrigger;
                    this.m_strDialogMenu += "\t";
                }
            }
        }

        
// Function       :   public void AddTrigger(const char *)
// Function       :   public void SetTrigger(const char *)

        public bool HasDialog()
        {
            return this.m_strDialogTitle.Length > 0;
        }

        public void ShowDialog()
        {
            if (this.m_strDialogTitle.Length > 0 || this.m_strDialogText.Length > 0)
            {
                uint npc = this.GetLastContactLong("npc");
                Messages.SendDialogMessage(this, npc, this.m_nDialogType, this.m_strDialogTitle, this.m_strDialogText, this.m_strDialogMenu);
                this.m_nDialogType = 0;
                this.m_strDialogTitle = "";
                this.m_strDialogText = "";
            }

        }

        public bool IsValidTrigger(string szTrigger)
        {
            string[] items = this.m_strDialogMenu.Split('\t');
            
            foreach (string s in items)
            {
                if (s == szTrigger)
                    return true;
            }
            return false;
        }

        public bool AddHotspot(GameContent.HotSpot pHotSpot)
        {
            lock (this.m_vPendingHotSpots)
            {
                this.m_vPendingHotSpots.Add(new RappelzPair<int, GameContent.HotSpot>(0, pHotSpot));
            }

            return true;
        }

        public bool RemoveHotspots(int quest_id)
        {
            lock (this.m_vPendingHotSpots)
            {
                for (int i = this.m_vHotSpots.Count - 1; i >= 0; --i)
                {
                    if (this.m_vHotSpots[i].nQuestId == quest_id)
                        this.m_vPendingHotSpots.Add(new RappelzPair<int, GameContent.HotSpot>(1, this.m_vHotSpots[i]));
                }
            }
            return true;
        }

// Function       :   public void SetLastContactMarket(const char *)
    
        public string GetLastContactMarket()
        {
            return this.GetLastContactStr("market");
        }

        public void PendWarp(int x, int y, byte layer)
        {
            this.m_nPendWarpX = x;
            this.m_nPendWarpLayer = layer;
            this.m_nPendWarpY = y;
            this.m_StatusFlag |= StatusFlags.Invincible;

            if (this.m_pMainSummon != null)
                this.m_pMainSummon.m_StatusFlag |= StatusFlags.Invincible;

            if (this.m_pSubSummon != null)
                this.m_pSubSummon.m_StatusFlag |= StatusFlags.Invincible;
            this.m_nWarpEndTime = Globals.GetArTime();
        }

        public void SetLastContact(string szKey, uint nValue)
        {
            this.SetLastContact(szKey, nValue.ToString());
        }

        public void SetLastContact(string szKey, string szValue)
        {
            if(this.m_hsContact.ContainsKey(szKey))
            {
                this.m_hsContact[szKey] = szValue;
            }
            else
            {
                this.m_hsContact.Add(szKey, szValue);
            }
        }



        public string GetLastContactStr(string szKey)
        {
            string res = "";
            if(m_hsContact.ContainsKey(szKey))
                res = m_hsContact[szKey];
            return res;
        }

        public uint GetLastContactLong(string szKey)
        {
            string szValue = this.GetLastContactStr(szKey);
            return Marshal.ToUInt32(szValue);
        }

        public int GetLoginDuration()
        {
            uint res = this.m_nLogoutTime;
            if (res == 0)
                res = Globals.GetArTime();
            return (int)((res - this.m_nLoginTime) / 100);

        }
// Function       :   public unsigned long GetLogoutTime()
// Function       :   public int GetLoginCount()
// Function       :   public unsigned long GetLogoutTimer()
// Function       :   public void SetLogoutTimer(unsigned long)
        public void SetContinuousPlayTime(uint continuous_play_time)
        {
/*
            RapplezState stamina_save = null;

            if ( GameRule.nMaxTiredGameTime >= continuous_play_time )
                stamina_save = GetState(STAMINA_SAVE);

            if (stamina_save != null)
            {
                if (stamina_save.IsHolded())
                {
                    if (continuous_play_time < GameRule.nMaxHealthyGameTime && (GetPCBangMode() != 2 || GameRule.bApplyStaminaBonusInPremiumPCBang) )
                    {
                        stamina_save.ReleaseRemainDuration();
//                        ((void (__thiscall *)(_DWORD, _DWORD, _DWORD))v2->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr[19].IsDeleteable)(this, stamina_save,0);
                    }
                }
                else
                {
                    if (continuous_play_time >= GameRule.nMaxHealthyGameTime )
                    {
                        stamina_save.HoldRemainDuration();
//                        ((void (__thiscall *)(_DWORD, _DWORD, _DWORD))v2->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr[19].IsDeleteable)(this, stamina_save,0);
                    }
                }
            }
*/

            m_nContinuousPlayTime = continuous_play_time;
            Messages.SendPropertyMessage(this, this.m_hHandle, "playtime", GetContinuousPlayTime());
        }

        public uint GetContinuousPlayTime()
        {
            uint result;

            if(IsGameTimeLimited())
                result = m_nContinuousPlayTime;
            else
                result = 0;
            return result;
        }
// Function       :   public void SetContinuousLogoutTime(unsigned long)
        public uint GetContinuousLogoutTime()
        {
            uint result;

            if(IsGameTimeLimited())
                result = m_nContinuousLogoutTime;
            else
                result = 0;
            return result;
        }
// Function       :   public void SetLastContinuousPlayTimeProcTime(unsigned long)

        public uint GetLastContinuousPlayTimeProcTime()
        {
            uint result;

            if (this.IsGameTimeLimited())
                result = this.m_nLastContinuousPlayTimeProcTime;
            else
                result = 0;
            return result;
        }

        public void AddFavor(int favor_id, int favor)
        {
            SetFavor(favor_id, favor, true);
        }

        public void SetFavor(int favor_id, int favor, bool bDBJob)
        {
            foreach (FavorInfo f in m_vFavorInfo)
            {
                if(f.favor_id == favor_id)
                {
                    f.favor = favor;
                    return;
                }
            }

            m_vFavorInfo.Add(new FavorInfo(favor_id, favor));
            if (bDBJob)
            {
                this.DBQuery(new DB_InsertFavor(this, favor_id, favor));
            }

        }

        public int GetFavor(int favor_id)
        {
            foreach (FavorInfo f in this.m_vFavorInfo)
            {
                if(f.favor_id == favor_id)
                    return f.favor;
            }
            return 0;
        }

// Function       :   public int StructPlayer::onDamage(struct StructCreature *, enum Elemental::Type, enum StructCreature::DamageType, int, bool)
// Function       :   public void StructPlayer::ProcImmoralPoint(struct StructPlayer *, int, bool)
// Function       :   public const unsigned int GetCompeteID()
// Function       :   public void SetCompeteID(const unsigned int)
// Function       :   public const bool IsCompeteDead()
// Function       :   public void SetCompeteDead(const bool)

        public bool ResurrectByCompete()
        {
            return false;
        }
// Function       :   public bool IsAutoUsed()
// Function       :   public bool IsMoveReq()
// Function       :   public void SetMoveReq(bool)
// Function       :   public void SetAutoUsed(bool)
// Function       :   public bool IsWarpEnded()
// Function       :   public void SetWarpEnded(bool)
// Function       :   public int GetRegionUpdateNeedCount()
// Function       :   public void IncRegionUpdateNeedCount()

        public void DecRegionUpdateNeedCount()
        {
            Interlocked.Decrement(ref this.m_nRegionUpdateNeedCount);
        }
// Function       :   public int GetInvalidScriptTriggerCount()
// Function       :   public void IncInvalidScriptTriggerCount()
// Function       :   public bool StructPlayer::IsTradableWith(struct StructPlayer *)
// Function       :   public void StructPlayer::StartTrade(struct StructPlayer *)
// Function       :   public bool IsTrading()
// Function       :   public bool IsTradeFreezed()
// Function       :   public bool IsTradeConfirm()
// Function       :   public unsigned int GetTradeTarget()
// Function       :   public const struct StructGold GetTradeGold()
// Function       :   public bool StructPlayer::AddItemToTradeWindow(struct StructItem *, const __int64 &)
// Function       :   public bool StructPlayer::RemoveItemFromTradeWindow(struct StructItem *, const __int64 &)
// Function       :   public void StructPlayer::AddGoldToTradeWindow(const struct StructGold &)
// Function       :   public void StructPlayer::FreezeTrade()
// Function       :   public void StructPlayer::ConfirmTrade()
// Function       :   public bool StructPlayer::CheckTradeWeight()
// Function       :   public bool StructPlayer::CheckTradeItem()
// Function       :   public bool StructPlayer::ProcessTrade()

        public void CancelTrade(bool bIsNeedBroadcast)
        {

        }

        public bool ResurrectByPotion()
        {
            return false;
        }

        public bool ClearExpiredItem()
        {
            if (this.clearExpiredItem(this.m_Storage.m_vExpireItemList) || this.clearExpiredItem(this.m_Inventory.m_vExpireItemList))
                return true;

            return false;
        }

        public bool ClearExpiredElementalEffect()
        {
            return false;
        }

        public void AddToElementalEffectedItemList(Item pItem)
        {
            if(!this.m_vElementalEffectedItem.Contains(pItem))
            {
                this.m_vElementalEffectedItem.Add(pItem);
            }
        }

        public void RemoveFromElementalEffectedItemList(Item pItem)
        {
            if(this.m_vElementalEffectedItem.Contains(pItem))
            {
                this.m_vElementalEffectedItem.Remove(pItem);
            }
        }
// Function       :   public int GetRideSpeedModifier()
// Function       :   public void StructPlayer::SetPCBangMode(char)

        public byte GetPCBangMode()
        {
            return 0;
        }
// Function       :   public void SetEventCode(int)
// Function       :   public int GetEventCode()
// Function       :   public void SetPlayTime(int)
// Function       :   public int GetPlayTime()
// Function       :   public void SetLastPlayTimeUpdateTime(unsigned long)
// Function       :   public unsigned long GetLastPlayTimeUpdateTime()
// Function       :   public void SetNextAuctionUsableTime(unsigned long)
// Function       :   public unsigned long GetNextAuctionUsableTime()
        public bool IsGameTimeLimited()
        {
            bool result = false;
            if(GameRule.bLimitGameTime)
            {
                if(m_nAge <= GameRule.nMaxGameTimeLimitedAge)
                    result = true;
            }
            return result;
        }
// Function       :   public void SetAge(int)
// Function       :   public const int GetAge()

        public void SendCharacterInfo()
        {
            this.CalculateStat();
            this.quadTreeItem.Set(this);//StructCreature::QuadTreeItem::Set(&v3->quadTreeItem, v3);
            this.quadTreeItem.AddMe();
            this.Login();

            foreach (Summon s in m_vSummonList)
            {
                Messages.SendAddSummonMessage(this, s);
            }

            foreach(Pet p in this.m_vPetList)
            {
                Messages.SendAddPetMessage(this, p);
            }

            Messages.SendItemList(this, false);
            Messages.SendCreatureEquipMessage(this, false);

            foreach (Summon s in m_vSummonList)
            {
                Messages.SendSkillMessage(this, s, -1);
            }

            foreach (Summon s in m_vSummonList)
            {
                Messages.SendTotalItemWearInfoMessage(this, s);
            }

            Messages.SendWearMessage(this);
            Messages.SendGoldChaosUpdateMsg(this);
            Messages.SendPropertyMessage(this, m_hHandle, "chaos", m_nChaos);
            Messages.SendPropertyMessage(this, m_hHandle, "tp", m_nTP);
//            Messages.SendPropertyMessage(this, m_hHandle, "ap", 0);
            Messages.SendLevelMsg(this, this);
            Messages.SendExpMsg(this, this);
            Messages.SendJobInfo(this, this);
            Messages.SendSkillMessage(this, this, -1);
            Messages.SendBeltSlotInfo(this);
            Messages.SendGameTime(this);

            Messages.SendPropertyMessage(this, m_hHandle, "dk_count", m_nDKC);
            Messages.SendPropertyMessage(this, m_hHandle, "pk_count", m_nPKC);
            Messages.SendPropertyMessage(this, m_hHandle, "immoral", Marshal.ToInt64(m_fImmoralPoint));
            Messages.SendPropertyMessage(this, this.m_hHandle, "huntaholicpoint", this.GetHuntaholicPoint());

            foreach(Item item in m_Inventory.m_vList)
            {
                if(item.m_pItemBase.nGroup == 10)
                {
                    if (item.m_Instance.Socket[0] == this.m_nUID)
                    {
                        this.BindSkillCard(item);
                    }
                    else if (item.m_Instance.Socket[1] != 0)
                    {
                        Creature c = this.GetSummon(item.m_Instance.nOwnSummonUID);
                        if(c != null)
                            c.BindSkillCard(item);
                    }
                }
            }

//            v19 = RappelzServer.Instance._LockObjectWithVisibleRange((ArcadiaLock *)(v1 - 80),&v3->baseclass_0.baseclass_0);
//            ArcadiaAutoLock::ArcadiaAutoLock((ArcadiaAutoLock *)(v1 - 100),v19);

            if (!this.bIsInWorld)
            {
                ChannelManager.EnterPlayerToLayer(this.m_layer);
                RappelzServer.Instance.AddObject(this);
                this.m_StatusFlag &= ~StatusFlags.FirstEnter;
            }

/*
            if (m_pSubSummon != null)
            {
                m_pSubSummon.m_StatusFlag |= 0x400;
                m_pSubSummon.AddNoise(XFastRandom(), XFastRandom(), 70);
                m_pSubSummon.m_layer = this.m_layer;
                RappelzServer.Instance.AddSummonToWorld(m_pSubSummon);
                TS_SC_UNSUMMON_NOTICE::TS_SC_UNSUMMON_NOTICE((TS_SC_UNSUMMON_NOTICE *)(v1 - 76));
                Data           :   this+0x7, Member, Type: unsigned int, summon_handle
                Data           :   this+0xB, Member, Type: unsigned long, unsummon_duration

                *(_DWORD *)(v1 - 69) = (**(int (***)(void))v3[1].m_csEnemy.m_cs.LockCount)();
                uint ct = Globals.GetArTime();
                if (ct <= m_nNextUnSummonTime)
                    *(_DWORD *)(v1 - 65) = 0;
                else
                    *(_DWORD *)(v1 - 65) = ct-m_nNextUnSummonTime;
                PendMessage(this, (TS_MESSAGE *)(v1 - 76));
            }
*/

            if (m_pMainSummon != null)
            {
                m_pMainSummon.m_StatusFlag |= StatusFlags.Invincible;
                m_pMainSummon.AddNoise(Globals.GetRandomInt32(), Globals.GetRandomInt32(), 70);
                m_pMainSummon.m_layer = this.m_layer;
                RappelzServer.Instance.AddSummonToWorld(m_pMainSummon);
            }

            if (m_pSummonedPet != null)
            {
                m_pSummonedPet.m_StatusFlag |= StatusFlags.Invincible;
                m_pSummonedPet.AddNoise(Globals.GetRandomInt32(), Globals.GetRandomInt32(), 24);
                m_pSummonedPet.m_layer = this.m_layer;
                RappelzServer.Instance.AddPetToWorld(m_pSummonedPet);
            }

            // this section is for states Creature.m_vStateList

            foreach (State s in this.m_vStateList)
            {
                this.onUpdateState(s, false);
            }

            Messages.SendPropertyMessage(this, this.m_hHandle, "stamina", this.m_nStamina);
            Messages.SendPropertyMessage(this, this.m_hHandle, "max_stamina", this.m_nMaxStamina);
            Messages.SendPropertyMessage(this, this.m_hHandle, "channel", ChannelManager.GetChannelNum(this.m_layer));
            Messages.BroadcastStatusMessage(this);
//            ArcadiaAutoLock::_ArcadiaAutoLock((ArcadiaAutoLock *)(v1 - 100));

        }

        public TimeSyncer m_TS;      // 0xFEC
// UserDefinedType:     TimeSyncer
// 
        public TCPConnection Connection;                // 0x1008

        public void SetAccount(int nAccountID, string szAccount)
        {
            m_szAccountName = szAccount;
            m_nAccountID = nAccountID;
        }

        public static long allocItemUID()
        {
            Interlocked.Increment(ref s_nItemIndex);
            return s_nItemIndex;
        }
        public static int allocSummonUID()
        {
            Interlocked.Increment(ref s_nSummonSID);
            return (int)s_nSummonSID;
        }
        public static int allocPetUID()
        {
            Interlocked.Increment(ref s_nPetSID);
            return (int)s_nPetSID;
        }

        // Function       :   public void SetSkinColor(unsigned long)

        public override uint GetSkinColor()
        {
            return m_nSkinColor;
        }

        public void RequestSecurityNo(int nMode)
        {
            using(PacketOut pak = new PacketOut(ClientOutPackets.SecurityNo))
            {
                pak.WriteInt32(nMode);
                this.Connection.SendTCP(pak);
            }
        }

        protected bool clearExpiredItem(List<Item> vExpireItemList)
        {
//             StructPlayer *v2; // edi@1
//             __int64 v3; // qax@1
//             void *v4; // esi@1
//             float v5; // eax@2
//             bool v6; // zf@3
//             ArMoveVector::MOVE_INFO *v7; // eax@5
//             int v8; // esi@18
//             int v9; // esi@23
//             ItemBase::ItemWearType v10; // ebx@26
//             int v11; // eax@27
//             int v12; // eax@35
//             ArMoveVector::MOVE_INFO *v13; // eax@39
//             int v14; // esi@39
//             ArMoveVector::MOVE_INFO *v15; // eax@39
//             char v16; // al@42
//             double v17; // st7@42
//             unsigned __int64 v18; // qax@42
//             double v19; // st7@42
//             ArcadiaServer *v20; // eax@42
//             __int64 count; // [sp+0h] [bp-50h]@39
//             std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > thisa; // [sp+8h] [bp-48h]@1
//             __int64 cur_t; // [sp+10h] [bp-40h]@1
//             std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > _Right; // [sp+18h] [bp-38h]@7
//             StructCreature::iterator itCreature; // [sp+20h] [bp-30h]@12
//             XScopedLock __scoped_lock; // [sp+28h] [bp-28h]@4
//             std::_Vector_iterator<StructPlayer::BOOTH_ITEM_INFO,std::allocator<StructPlayer::BOOTH_ITEM_INFO> > itBoothItem; // [sp+2Ch] [bp-24h]@4
//             std::_Vector_const_iterator<StructItem *,std::allocator<StructItem *> > it; // [sp+34h] [bp-1Ch]@1
//             int i; // [sp+3Ch] [bp-14h]@5
//             char bNeedToBroadcastEquipMessage; // [sp+42h] [bp-Eh]@1
//             const bool ret; // [sp+43h] [bp-Dh]@1
//             int v33; // [sp+4Ch] [bp-4h]@4
//             TS_WEAR_INFO msg; // [sp+50h] [bp+0h]@1
//             unsigned int v35; // [sp+194h] [bp+144h]@1
//             void *vExpireItemLista; // [sp+1A0h] [bp+150h]@1
// 
//             v35 = &msg ^ __security_cookie;
//             v2 = this;
//             v3 = _time64(0);
//             v4 = vExpireItemLista;
//             *&msg.elemental_effect_type[5] = vExpireItemLista;
//             *&msg.elemental_effect_type[1] = *(vExpireItemLista + 1);
//             cur_t = v3;
//             ret = 0;
//             bNeedToBroadcastEquipMessage = 0;
//             std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                 &it,
//                 *&msg.elemental_effect_type[1],
//                 vExpireItemLista);
//             *&msg.elemental_effect_type[5] = v4;
//             *&msg.elemental_effect_type[1] = *(v4 + 2);
//             std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                 &thisa,
//                 *&msg.elemental_effect_type[1],
//                 v4);
//             if ( !std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(&it, &thisa) )
//             {
//                 do
//                 {
//                     v5 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x;
//                     if ( *(LODWORD(v5) + 256) < cur_t )
//                     {
//                         v6 = v2->m_BoothStatus == 0;
//                         ret = 1;
//                         if ( !v6 )
//                         {
//                             s_BoothLock.baseclass_0.vfptr->Lock(&s_BoothLock);
//                             s_BoothLock.baseclass_0.m_pszFileName = "D:\\alienbrainWork\\Source Code\\@Rappelz\\Server\\GameServer_For_Update\\090721_GameServer\\Game\\Struct\\StructPlayer.cpp : StructPlayer::clearExpiredItem";
//                             s_BoothLock.baseclass_0.m_nLineNumber = 8176;
//                             __scoped_lock.m_lock = &s_BoothLock;
//                             v33 = 0;
//                             std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                                 &itBoothItem,
//                                 v2->m_vBoothItem._Myfirst,
//                                 &v2->m_vBoothItem.baseclass_0.___u0.baseclass_0);
//                             while ( 1 )
//                             {
//                                 std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                                     &_Right,
//                                     v2->m_vBoothItem._Mylast,
//                                     &v2->m_vBoothItem.baseclass_0.___u0.baseclass_0);
//                                 if ( std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
//                                          &itBoothItem,
//                                          &_Right) )
//                                     break;
//                                 i = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&itBoothItem);
//                                 v7 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it);
//                                 if ( *i == LODWORD(v7->end.x) )
//                                 {
//                                     vector_fast_erase<std::vector<StructPlayer::BOOTH_ITEM_INFO_std::allocator<StructPlayer::BOOTH_ITEM_INFO>>_std::_Vector_iterator<StructPlayer::BOOTH_ITEM_INFO_std::allocator<StructPlayer::BOOTH_ITEM_INFO>>>(
//                                         &v2->m_vBoothItem,
//                                         &itBoothItem);
//                                     StructPlayer::broadcastBoothInfo(v2);
//                                     break;
//                                 }
//                                 std::_Vector_const_iterator<StructCreature::HateModifier_std::allocator<StructCreature::HateModifier>>::operator__(&itBoothItem);
//                             }
//                             v33 = -1;
//                             s_BoothLock.baseclass_0.vfptr->UnLock(&s_BoothLock);
//                         }
//                         if ( *(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x)
//                              + 296) == -1 )
//                         {
//                             if ( *(*(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x)
//                                    + 332)
//                                  + 12) == 13 )
//                             {
//                                 *&i = 0.0;
//                                 v8 = v2->m_aBeltSlotCard;
//                                 while ( *(v8 - 24) != LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x) )
//                                 {
//                                     if ( *v8 == LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x) )
//                                     {
//                                         StructPlayer::PutOffBelt(v2, i);
//                                         SendBeltSlotInfo(v2);
//                                         goto LABEL_39;
//                                     }
//                                     ++i;
//                                     v8 += 4;
//                                     if ( i >= 6 )
//                                         goto LABEL_39;
//                                 }
//                                 v9 = *(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x)
//                                      + 336);
//                                 if ( v9 )
//                                 {
//                                     if ( *(v9 + 68) )
//                                         StructPlayer::UnSummon(v2, v9);
//                                     v10 = 0;
//                                     do
//                                     {
//                                         v11 = *v9;
//                                         *&msg.elemental_effect_type[5] = v10;
//                                         if ( (*(v11 + 160))(v9, v10) )
//                                             StructCreature::Putoff(v9, v10);
//                                         ++v10;
//                                     }
//                                     while ( v10 < 24 );
//                                     v2->m_aBindSummonCard[i] = 0;
//                                 }
//                                 SendCreatureEquipMessage(v2, 0);
//                             }
//                             else
//                             {
//                                 if ( *(*(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x)
//                                        + 332)
//                                      + 12) == 18 )
//                                 {
//                                     v12 = *(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x)
//                                           + 340);
//                                     if ( v12 )
//                                     {
//                                         if ( *(v12 + 68) && v2->m_pSummonedPet == v12 )
//                                             StructPlayer::UnSummonPet(v2);
//                                     }
//                                 }
//                             }
//                         }
//                         else
//                         {
//                             *&msg.elemental_effect_type[5] = *(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x)
//                                                              + 344);
//                             StructCreature::get(&itCreature, *&msg.elemental_effect_type[5]);
//                             v33 = 1;
//                             if ( itCreature.baseclass_0.m_pObject )
//                             {
//                                 *&msg.elemental_effect_type[5] = *(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x)
//                                                                  + 296);
//                                 StructCreature::putoffItem(itCreature.baseclass_0.m_pObject, *&msg.elemental_effect_type[5]);
//                             }
//                             if ( itCreature.baseclass_0.m_pObject == v2 )
//                                 bNeedToBroadcastEquipMessage = 1;
//                             v33 = -1;
//                             itCreature.baseclass_0.vfptr = &StructCreature::iterator::_vftable_;
//                             GameObject::iterator::_iterator(&itCreature.baseclass_0);
//                         }
//         LABEL_39:
//                         v13 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it);
//                         v14 = (**LODWORD(v13->end.x))();
//                         count = *(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it)->end.x)
//                                 + 240);
//                         v15 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&it);
//                         *&msg.elemental_effect_type[5] = &count;
//                         *&msg.elemental_effect_type[1] = LODWORD(v15->end.x);
//                         StructPlayer::EraseItem(v2, *&msg.elemental_effect_type[1], &count);
//                         *&msg.elemental_effect_type[5] = v14;
//                         PrintfChatMessage(0, 20, "@SYSTEM", v2, "ITEM_EXPIRE|%u");
//                         v4 = vExpireItemLista;
//                     }
//                     std::_Vector_const_iterator<AutoAuctionInfo___std::allocator<AutoAuctionInfo__>>::operator__(&it);
//                     *&msg.elemental_effect_type[5] = v4;
//                     *&msg.elemental_effect_type[1] = *(v4 + 2);
//                     std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                         &thisa,
//                         *&msg.elemental_effect_type[1],
//                         v4);
//                 }
//                 while ( !std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
//                              &it,
//                              &thisa) );
//                 if ( bNeedToBroadcastEquipMessage )
//                 {
//                     TS_WEAR_INFO::TS_WEAR_INFO(&msg);
//                     GetWearMsg(v2, &msg);
//                     v16 = v2->baseclass_0.baseclass_0.baseclass_0.layer;
//                     *&i = g_nRegionSize;
//                     v17 = v2->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.y;
//                     LOBYTE(__scoped_lock.m_lock) = v16;
//                     v18 = (v17 / *&i);
//                     v19 = v2->baseclass_0.baseclass_0.baseclass_0.mv.baseclass_0.x / *&i;
//                     *&msg.elemental_effect_type[5] = &msg;
//                     *(&msg.itemLevel[23] + 1) = __PAIR__(__scoped_lock.m_lock, v18);
//                     *(&msg.itemLevel[22] + 1) = v19;
//                     v20 = ArcadiaServer::Instance();
//                     ArcadiaServer::Broadcast(
//                         v20,
//                         *(&msg.itemLevel[22] + 1),
//                         *(&msg.itemLevel[23] + 1),
//                         msg.elemental_effect_type[1],
//                         *&msg.elemental_effect_type[5]);
//                 }
//             }
            return false;// return ret;
        }


        protected override ushort putonItem(ItemBase.ItemWearType pos, Item item)
        {
            ushort result;
            float posa; // [sp+14h] [bp+8h]@6

            if (pos == ItemBase.ItemWearType.WearShield)
            {
                if (item.m_pItemBase.nGroup == 1 )
                    this.m_StatusFlag |= StatusFlags.UsingDoubleWeapon;
            }
            result = base.putonItem(pos, item);
            if (result == 0)
            {
                if (this.m_anWear[(int)pos] != null && this.m_anWear[(int)pos].m_hHandle == item.m_hHandle)
                {
                    this.m_Inventory.m_fWeightModifier -= item.GetWeight();
                }
                this.UpdateWeightWithInventory();
                this.UpdateQuestStatusByItemUpgrade();
                result = 0;
            }
            return result;
        }

        protected override ushort putoffItem(ItemBase.ItemWearType pos)
        {
            ushort result = 0;
            int i;
            bool found;

            Item item = this.m_anWear[(int)pos];
            if (this.m_anWear[(int)pos] == null)
                return 1;

            switch(pos)
            {
                case ItemBase.ItemWearType.WearArmulet:
                    if (this.m_nChaos != 0)
                        return 6;
                    break;

                case ItemBase.ItemWearType.WearShield:
                    if (this.m_anWear[1].m_pItemBase.nGroup == 1)
                        this.m_StatusFlag &= ~StatusFlags.UsingDoubleWeapon;
                    if (this.m_anWear[15] != null)
                        this.putoffItem(ItemBase.ItemWearType.WearDecoShield);
                    break;

                case ItemBase.ItemWearType.WearWeapon:
                    if (this.IsUsingDoubleWeapon())
                        this.putoffItem(ItemBase.ItemWearType.WearShield);
                    this.putoffItem(ItemBase.ItemWearType.WearDecoWeapon);
                    break;

                case ItemBase.ItemWearType.WearDecoWeapon:
                    if (this.IsUsingDoubleWeapon() && this.m_anWear[15] != null)
                        this.putoffItem(ItemBase.ItemWearType.WearDecoShield);
                    break;

                case ItemBase.ItemWearType.WearBelt:
                    found = false;
                    for (i = 0; i < 6; ++i)
                    {
                        if (this.m_aBeltSlotCard[i] != null)
                        {
                            found = true;
                            this.PutOffBelt(i);
                        }
                    }
                    if (found)
                        Messages.SendBeltSlotInfo(this);
                    break;

                case ItemBase.ItemWearType.WearRideItem:
                    if (this.m_nRidingStateUid != 0)
                        this.RemoveState(this.m_nRidingStateUid);
                    break;

            }

            result = base.putoffItem(pos);
            if (item != null)
            {
                this.m_Inventory.m_fWeightModifier += item.GetWeight();
            }
            this.UpdateWeightWithInventory();
            this.UpdateQuestStatusByItemUpgrade();
            return result;
        }
// Function       :   protected void StructPlayer::procDecreaseEXPAndDropItem(struct StructPlayer *, struct StructItem * *, struct StructItem * *)
// Function       :   protected void StructPlayer::addToBoothWatcher(struct StructPlayer *)
// Function       :   protected void StructPlayer::removeFromBoothWatcher(struct StructPlayer *)
        protected bool isInLocationType(byte nLocationType)
        {
            return m_WorldLocation != null && m_WorldLocation.location_type == nLocationType;
        }
// Function       :   private void setLocation(int)
// Function       :   private const char * StructPlayer::getClassName()

        private void processHotspots(uint ct)
        {
            List<GameContent.HotSpot> vSpots = new List<GameContent.HotSpot>();
            ArPosition pos = this.GetCurrentPosition(ct);
            // we should process our hotspots now
            lock (this.m_vHotSpots)
            {
                foreach (GameContent.HotSpot hs in this.m_vHotSpots)
                {
                    bool bShouldFire = false;
                    if (hs.bIsSquare)
                    {
                        if (pos.x > hs.x - hs.sx && pos.x < hs.x + hs.sx)
                        {
                            if (pos.y > hs.y - hs.sy && pos.y < hs.y + hs.sy)
                            {
                                if(hs.nNeededStateId == 0 || this.GetState((State.StateCode)hs.nNeededStateId) != null)
                                    bShouldFire = true;
                            }
                        }
                    }
                    else
                    {
                        ArPosition center = new ArPosition(hs.x, hs.y, 0);
                        if (Math.Abs(center.GetDistance(pos)) < hs.sx)
                            bShouldFire = true;
                    }
                    if (bShouldFire && !hs.bHasFired && hs.lastRegen + hs.regenTime < ct && (hs.fireCount == 0 || hs.regenTime > 0))
                    {
                        LuaVM.Instance.RunString(this, hs.szEnterScript);
                        hs.lastRegen = ct;
                        hs.bHasFired = true;
                        hs.fireCount++;
                    }
                    if (!bShouldFire)
                    {
                        if (hs.bHasFired && !String.IsNullOrEmpty(hs.szExitScript))
                            LuaVM.Instance.RunString(this, hs.szExitScript);
                        hs.bHasFired = false;
                    }
                }
            }
            lock (this.m_vPendingHotSpots)
            {
                foreach (RappelzPair<int,GameContent.HotSpot> hs in this.m_vPendingHotSpots)
                {
                    if(hs.First == 1)
                    {
                        if (this.m_vHotSpots.Contains(hs.Second))
                            this.m_vHotSpots.Remove(hs.Second);
                    }
                    else
                    {
                        if (!this.m_vHotSpots.Contains(hs.Second))
                            this.m_vHotSpots.Add(hs.Second);
                    }
                }
                this.m_vPendingHotSpots.Clear();
            }

        }

        public override void onProcess(int nThreadIdx)
        {
            if (!this.bIsInWorld )
                return;

            uint ct = Globals.GetArTime();

            if (this.m_nLogoutTimer != 0 && this.m_nLogoutTimer < ct)
            {
                this.LogoutNowWithAccount(6);
                return;
            }
            if (this.IsPendWarp())
            {
                this.ProcessWarp();
                this.m_nLastProcessTime = ct;
            }
            RLock rl1 = RappelzServer.Instance._LockObjectWithVisibleRange(this);
            AutoLock al1 = new AutoLock(rl1.handle);
            bool bIsMoving = this.mv.IsMoving(ct);

            processHotspots(ct);

            //ArcadiaAutoLock::_ArcadiaAutoLock(&_lock);
            if (!bIsMoving && this.IsActable())
            {
                this.onAttackAndSkillProcess();
                this.m_nLastProcessTime = ct;
            }

            RLock rl2 = RappelzServer.Instance._LockObjectWithVisibleRange(this);
            AutoLock al2 = new AutoLock(rl2.handle);

            if ((this.m_StatusFlag & StatusFlags.MovePending) != 0)
            {
                this.processPendingMove();
                this.m_nLastProcessTime = ct;
            }
            else if ((this.m_StatusFlag & StatusFlags.Invincible) != 0)
            {
                if (this.m_nWarpEndTime + 2000 < ct)
                {
                    this.m_StatusFlag &= ~StatusFlags.Invincible;
                    Summon s = this.m_pMainSummon;
                    if (s != null)
                        s.m_StatusFlag &= ~StatusFlags.Invincible;
                    s = this.m_pSubSummon;
                    if (s != null)
                        s.m_StatusFlag &= ~StatusFlags.Invincible;
                }
            }
            else if (this.m_hEnemy != 0 && !this.IsUsingSkill() && !bIsMoving)
            {
                if (this.m_nLastProcessTime != 0 && this.m_nLastProcessTime + 500 < ct)
                {
                    RappelzServer.Instance.SetObjectPriority(this, SchedulerObject.Priority.Low);
                    this.m_nLastProcessTime = 0;
                }
                else
                {
                    this.m_nLastProcessTime = ct;
                }
            }

//             if (this.m_nWorldLocationId != 110900 && Globals.GetRandomInt32(0, 10000) == 0)
//             {
//                 LuaVM.Instance.RunString(this, "kick_auto_to_another_world()");
//             }
//            ArcadiaAutoLock::_ArcadiaAutoLock(&thisa);
            this.procPendingUnSummon();
            this.procPendingUnSummonPet();
            if (this.IsGameTimeLimited())
            {
                if (this.GetContinuousPlayTime() >= GameRule.nMaxTiredGameTime)
                {
                    int hid = HuntaholicManager.Instance.GetHuntaholicID(this.mv);
                    if (hid != 0)
                    {
                        if ( HuntaholicManager.Instance.IsHuntaholicLobby(this.mv))
                        {
                            HuntaholicManager.Instance.LeaveInstanceDungeon(hid, this);
                        }
                        else
                        {
                            HuntaholicManager.Instance.QuitHunting(hid, this, true, -1);
                        }
                    }
                }
            }
        }

// Function       :   private void StructPlayer::onHPChange(int)

        public void onChangeProperty(string strKey, string data)
        {
            switch(strKey)
            {
                case "hp":
                    Messages.BroadcastHPMPMsg(this, Marshal.ToInt32(data), 0, false);
                    return;

                case "lvl":
                case "level":
                    this.SetEXP(GameContent.GetNeedExp(Marshal.ToInt32(data)));
                    return;

                case "exp":
                    this.onExpChange();
                    return;

                case "gold":
                    Messages.SendGoldChaosUpdateMsg(this);
                    return;

                case "skin_color":
                    Messages.BroadcastPropertyMessage((uint)(this.mv.x / GameContent.g_nRegionSize),(uint)(this.mv.y / GameContent.g_nRegionSize), (sbyte)this.m_layer, this.m_hHandle, "skin_color", this.GetSkinColor());
                    return;

                case "job":
                    this.m_nJobDepth = this.GetJobDepth();
                    this.m_QuestManager.UpdateQuestStatusByJobLevel(this.GetJobDepth(), this.GetJobLevel());
                    this.CalculateStat();

                    if (this.m_nGuildId != 0)
                        GuildManager.Instance.OnChangeCharacterJob(this.m_nGuildId, this.GetName(), this.GetJobId());

                    if (this.m_nPartyId != 0)
                        PartyManager.Instance.OnChangeCharacterJob(this.m_nPartyId, this.GetName(), this.GetJobId());

                    ServerLog.Log((ushort)0x900, this.m_nAccountID, this.GetSID(), 0, this.GetPrevJobId(this.m_nJobDepth - 1), this.GetJobId(), this.GetPrevJobId(this.m_nJobDepth - 1),
                        this.GetJobLevel(),0,0,0,0,m_szAccountName,this.GetName(),"","");
                    return;

                case "jlvl":
                case "job_level":
                    this.onJobLevelUp();
                    this.m_nJobDepth = this.GetJobDepth();
                    this.m_QuestManager.UpdateQuestStatusByJobLevel(this.GetJobDepth(),this.GetJobLevel());
                    this.CalculateStat();
                    return;

                case "chaos":
                    this.m_QuestManager.UpdateQuestStatusByParameter(99, this.m_nChaos);
                    break;

                case "immoral":
                    Messages.BroadcastStatusMessage(this);
                    break;
            }

            Messages.SendPropertyMessage(this, this.m_hHandle, strKey, data);
        }

        protected override void applyStatByState()
        {
// .text:004560A5 var_94          = qword ptr -94h
            float fDistEXP;                                     // 40   28h
            int[] nLevel = new int[3];                          // 44   2Ch
            int[] nOriginalLevel = new int[3];                  // 56   38h
            List<RappelzPair<int,int>> vDecreaseList = new List<RappelzPair<int,int>>();    // 68   44h
            float fDistJP;                                      // 88   58h
// .text:004560A5 itDecrease      = std::_Vector_iterator<std::pair<int,int>,std::allocator<std::pair<int,int> > > ptr  64h
// .text:004560A5 it              = std::_Vector_iterator<StructState,std::allocator<StructState> > ptr  6Ch
            int i;


            if (this.m_vStateList.Count > 0)
            {
                base.applyStatByState();
//                 v5 = 0;
//                 v6 = *(v4 + 4);
//                 *(v1 - 4) = 0;
//                 if ( !std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
//                           (v1 + 108),
//                           (v1 + 92)) )
/*
                {
                    foreach (State s in this.m_vStateList)
                    {
                        nOriginalLevel[0] = s.m_nLevel[0];
                        nOriginalLevel[1] = s.m_nLevel[1];
                        nOriginalLevel[2] = s.m_nLevel[2];
                        std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                            (v1 + 100),
                            *(v1 + 72),
                            (v1 + 68));
                        while ( 1 )
                        {
                            std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                                (v1 + 32),
                                *(v1 + 76),
                                (v1 + 68));
                            if ( std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                                     (v1 + 100),
                                     (v1 + 32)) )
                                break;
                            v8 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 100));
                            if ( LODWORD(v8->end.x) == LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108))->end.z) )
                            {
                                nLevel[0] = 0;
                                nLevel[1] = 0;
                                nLevel[2] = 0;

                                for ( *(v1 + 116) = v5; ; v5 = *(v1 + 116) )
                                {
                                    v9 = *(v1 + v5 + 64)
                                       - LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 100))->end.y);
                                    v10 = v1 + v5 + 52;
                                    *v10 = v9;
                                    if ( v9 < 0 )
                                    {
                                        v11 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 100));
                                        *v10 = 0;
                                        LODWORD(v11->end.y) = -v9;
                                    }
                                    *(v1 + 116) -= 4;
                                    if ( *(v1 + 116) < -8 )
                                        break;
                                }
                                s.m_nLevel[0] = nLevel[0];
                                s.m_nLevel[1] = nLevel[1];
                                s.m_nLevel[2] = nLevel[2];
                                break;
                            }
                            std::_Vector_const_iterator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>_std::allocator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>>>::operator__((v1 + 100));
                        }

                        if (s.GetLevel() != 0)
                        {
                            v14 = s.GetEffectType() - 112;
                            if (s.GetEffectType() != 112)
                            {
                                if (s.GetEffectType() == 113)
                                {
                                    v15 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                    v16 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                    *(v1 + 84) = StructState::GetValue(v16, (v1 - 44), 1)->value / 10000.0;
                                    v17 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                    *(v1 + 116) = StructState::GetLevel(v15);
                                    v18 = *(v1 + 116) * *(v1 + 84);
                                    v19 = StructState::GetValue(v17, (v1 + 24), 0);
                                    v3->m_fGiveEXPMod = c_fixed<10000>::operator_<double>(v19, (v1 - 28), v18)->value / 10000.0
                                                      + v3->m_fGiveEXPMod;
                                    v20 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                    v21 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                    *(v1 + 84) = StructState::GetValue(v21, (v1 - 60), 3)->value / 10000.0;
                                    v22 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                    *(v1 + 116) = StructState::GetLevel(v20);
                                    v23 = *(v1 + 116) * *(v1 + 84);
                                    v24 = StructState::GetValue(v22, (v1 - 36), 2);
                                    v3->m_fGiveJPMod = c_fixed<10000>::operator_<double>(v24, (v1 + 8), v23)->value / 10000.0
                                                     + v3->m_fGiveJPMod;
                                    v25 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                    v26 = StructState::GetValue(v25, (v1 - 20), 4)->value / 10000.0 != 0.0;
                                    v3->m_bApplySummonEXPLimit = v26;
                                }
                            }
                            else
                            {
                                v27 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                v28 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                v29 = StructState::GetValue(v28, (v1 - 52), 0);
                                *(v1 + 116) = StructState::GetLevel(v27);
                                *(v1 + 40) = *(v1 + 116) * v29->value / 10000.0;
                                v30 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                v31 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                v32 = StructState::GetValue(v31, (v1 + 16), 1);
                                *(v1 + 116) = StructState::GetLevel(v30);
                                *(v1 + 88) = *(v1 + 116) * v32->value / 10000.0;
                                v33 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                v34 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((v1 + 108));
                                v35 = StructState::GetValue(v34, v1, 4);
                                *(v1 + 116) = StructState::GetLevel(v33);
                                v3->m_nDoubleSummonTime = (*(v1 + 116) * v35->value / 10000.0 * 100.0 + v3->m_nDoubleSummonTime);
                                v3->m_fDistEXPMod = v3->m_fDistEXPMod + *(v1 + 40);
                                v3->m_fDistJPMod = *(v1 + 88) + v3->m_fDistJPMod;
                            }
                        }
                        s.m_nLevel[0] = nOriginalLevel[0];
                        s.m_nLevel[1] = nOriginalLevel[1];
                        s.m_nLevel[2] = nOriginalLevel[2];
                        if ( !std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                                  (v1 + 108),
                                  (v1 + 92)) )
                        {
                            v5 = 0;
                            continue;
                        }
                        break;
                    }
                }
*/
            }

        }

        protected override void applyState(State state)
        {
            int stateType = state.GetEffectType();
            if (stateType == 200 )
            {
                if ((this.m_StatusFlag & StatusFlags.MoveSpeedFixed) == 0)
                    this.m_Attribute.nMoveSpeed = state.GetValue(0);
                this.m_nRidingStateUid = state.m_nUID;
                return;
            }

            if (stateType == 0)
            {
                if (state.m_nCode == State.StateCode.StaminaSave)
                {
                    this.m_bStaminaSave = true;
                    return;
                }
                if (state.m_nCode == State.StateCode.SummonGrowingCrackerWithoutPenalty)
                {
                    this.m_eSummonStaminaSaveType = SummonStaminSaverType.SummonStaminaSaverWithoutPenalty;
                    return;
                }
                if (state.m_nCode == State.StateCode.SummonGrowingCrackerWithPenalty)
                {
                    this.m_eSummonStaminaSaveType = SummonStaminSaverType.SummonStaminaSaverWithPenalty;
                    return;
                }
                if (state.m_nCode == State.StateCode.PassDamage)
                {
                    this.m_fPassDamageRatio = state.GetValue(0) + (state.GetValue(1) * state.GetLevel());
                    return;
                }
                if (state.m_nCode == State.StateCode.FusionWithSummon)
                {
                    this.m_nMaxHP = this.m_nMaxHP + ((int)(state.GetValue(0) + (state.GetValue(1) * state.GetLevel())) * this.m_nMaxHP);
                    this.m_nMaxMP = this.m_nMaxMP + ((int)(state.GetValue(2) + (state.GetValue(3) * state.GetLevel())) * this.m_nMaxMP);
                    this.m_bIsSummonable = false;
                    return;
                }

                base.applyState(state);
                return;
            }
            if (stateType != 114)
            {
                base.applyState(state);
                return;
            }

            // harmony of life, beast disguise, etc
            if (state.GetValue(0) != 0.0f || state.GetValue(1) != 0.0f)
            {
                this.m_Attribute.nMoveSpeed = (state.GetValue(0) + (state.GetValue(1) * state.GetLevel()));
                this.m_StatusFlag |= StatusFlags.MoveSpeedFixed;
            }
            this.m_StatusFlag |= StatusFlags.FormChanged;
            if(state.GetValue(2) != 0.0)
            {
                this.m_StatusFlag |= StatusFlags.SkillCastable;
                this.m_StatusFlag |= StatusFlags.MagicCastable;
            }
            else
            {
                this.m_StatusFlag &= ~StatusFlags.SkillCastable;
                this.m_StatusFlag &= ~StatusFlags.MagicCastable;
            }
            this.m_bIsSummonable = state.GetValue(3) != 0.0f;
            this.m_nMaxHP = ((int)(state.GetValue(4) + (state.GetValue(5) * state.GetLevel())) * this.m_nMaxHP);
            this.m_nMaxMP = ((int)(state.GetValue(6) + (state.GetValue(7) * state.GetLevel())) * this.m_nMaxMP);

        }

        protected override void applyJobLevelBonus()
        {
            int[] levels = new int[4];
            int[] jobs = new int[4];
            CreatureStat stat = new CreatureStat();
            int i;
            int jobDepth;

            if (this.GetJobId() != 0)
            {
                jobDepth = this.GetJobDepth();
                for ( i = 0; i < this.GetJobDepth(); ++i)
                {
                    jobs[i] = this.GetPrevJobId(i);
                    levels[i] = this.GetPrevJobLevel(i);
                }

                jobs[i] = this.GetJobId();
                levels[i] = this.GetJobLevel();
                stat = GameContent.GetJobLevelBonus(jobDepth, jobs, levels);
                this.m_Stat.Add(stat);
            }

        }

        protected override void onExpChange()
        {
            int nAllianceID;    // dword ptr  36 24h
            int nGuildID;       // dword ptr  100 64h

            int level = 1;
            if (GameContent.GetNeedExp(1) <= this.m_nEXP)
            {
                do
                {
                    if (level >= 300)
                        break;
                    ++level;
                }
                while (GameContent.GetNeedExp(level) <= this.m_nEXP);
            }
            Messages.SendExpMsg(this,this);
            this.sendBonusExpJpMsg();
            int oldLevel = this.m_nLevel;
            if (level != 0 && level != oldLevel)
            {
                ServerLog.Log((ushort)0x8FD,this.m_nAccountID,this.GetSID(),0,this.m_nLevel, level,this.m_nMaxReachedLevel,0,0,0,0,0,
                    this.m_szAccountName, this.GetName(),"","");


                this.m_nLevel = level;
                if (level < oldLevel)
                {
                    this.CalculateStat();
                }
                else
                {
                    LuaVM.Instance.RunString(this, "on_player_level_up()");

                    if (this.m_nLevel > this.m_nMaxReachedLevel )
                        this.m_nMaxReachedLevel = this.m_nLevel;
                    Messages.SendNPCStatusInVisibleRange(this);
                    this.CalculateStat();
                    if (this.m_nHP != 0)
                    {
                        this.m_nHP = this.m_nMaxHP;
                        this.m_fMP = this.m_nMaxMP;
                    }
                    Messages.BroadcastHPMPMsg(this, 0, 0, false);

                    if (this.m_nGuildId > 0 )
                    {
                        GuildManager.Instance.OnChangeCharacterLevel(this.m_nGuildId, this.GetName(), this.GetLevel());
                    }
                    if (this.m_nPartyId != 0)
                    {
                        PartyManager.Instance.OnChangeCharacterLevel(this.m_nGuildId, this.GetName(), this.GetLevel());
                    }
                }
                this.setSummonUpdate();
                this.Save(false);
                Messages.BroadcastLevelMsg(this);

                nGuildID = this.m_nGuildId;
                nAllianceID = GuildManager.Instance.GetAllianceID(nGuildID);
                if (nAllianceID != 0)
                {

                    nGuildID = GuildManager.Instance.GetAllianceLeaderGuildID(nAllianceID);
                }
                if (nGuildID != 0)
                {
//                     if ( GuildManager.Instance.IsRaidLeader(nGuildID, this.GetName()))
//                     {
//                         if ( !GuildManager.Instance.IsLeader(nGuildID, this.GetName()) )
//                         {
//                             if (DungeonManager.Instance.IsRestrictedToEnter(GuildManager.Instance.GetRaidDungeonID(nGuildID), this, 0) )
//                             {
//                                 if ( PartyManager.Instance.IsExistAttackTeam(nGuildID) )
//                                 {
//                                     Messages.BroadcastPartyDestroy(this.m_nPartyId);
//                                     ServerLog.Log((ushort)0xD49, this.m_nAccountID,this.GetSID(),this.m_nPartyId,(long)this.mv.x,(long)this.mv.y,this.m_layer,
//                                         6,0,0,0,0,this.m_szAccountName,this.GetName(),PartyManager.Instance.GetPartyName(this.m_nPartyId),"");
// 
//                                     if ( !PartyManager.Instance.DestroyParty(PartyManager.Instance.GetAttackTeamLeadPartyID(this.m_nPartyId)) )
//                                     {
//                                         Globals.Log.Error("StructPlayer::onExpChange: Attack team destroy failed on level change.[{0}:{1} Lv.{2}]",
//                                             this.m_szAccountName, this.GetName(), this.m_nLevel);
//                                     }
//                                 }
//                                 if (nAllianceID != 0)
//                                 {
//                                     Messages.PrintfAllianceChatMessage(nAllianceID, "DISMISS_RAID_LEADER|{0}|3|", GuildManager.Instance.GetRaidLeaderName(nGuildID));
//                                 }
//                                 else
//                                 {
//                                     Messages.PrintfGuildChatMessage(110, nGuildID, "DISMISS_RAID_LEADER|{3}|3|",GuildManager.Instance.GetRaidLeaderName(nGuildID));
//                                 }
//                                 GuildManager.Instance.ClearRaidLeader(nGuildID);
//                             }
//                         }
//                     }
                }
            }
            else
            {
                if (this.m_nLastExpSaveTime + 3000 < Globals.GetArTime() )
                    this.Save(true);
            }

        }
// Function       :   private void StructPlayer::onMaxHavocChange()
// Function       :   private void StructPlayer::onHavocChange()
// Function       :   private void StructPlayer::onEnergyChange()

        protected override void onBeforeCalculateStat()
        {
            this.m_fPassDamageRatio = 0.0f;
            this.m_fDistEXPMod = 1.0f;
            this.m_fDistJPMod = 1.0f;
            this.m_bIsSummonable = true;
            this.m_nRideModifier = 0;
            this.m_nSpeedModifier = 0;
            this.m_nMaxWeightModifier = 0;
            this.m_fGiveEXPMod = 0.0f;
            this.m_bStaminaSave = false;
            this.m_fGiveJPMod = 0.0f;
            this.m_eSummonStaminaSaveType = 0;
            this.m_fActiveSummonExpAmp = 0.0f;
            this.m_nBeltSlotMax = 0;
            this.m_fDeactiveSummonExpAmp = 0.0f;
            this.m_nMaxStamina = 500000;
            this.m_bUsingTent = false;
            this.m_nStaminaRegenBonus = 0;
            this.m_nMaxChaos = 0;
            this.m_nDoubleSummonTime = 1000;
            this.m_bApplySummonEXPLimit = true;
            this.m_nRidingStateUid = 0;
            this.m_vSummonPassiveSkillList.Clear();
            this.m_vAmplifySummonPassiveSkillList.Clear();

        }

        protected override void onModifyStatAndAttribute()
        {
            Messages.SendStatInfo(this, this);
            Messages.SendPropertyMessage(this, m_hHandle, "max_havoc", m_nMaxHavoc);
            Messages.SendPropertyMessage(this, m_hHandle, "max_chaos", m_nMaxChaos);
            Messages.SendPropertyMessage(this, m_hHandle, "max_stamina", m_nMaxStamina);
        }

        protected override void onCompleteCalculateStat()
        {

        }

        protected override void applyPassiveSkillEffect(Skill skill)
        {
            if (skill.m_SkillBase.effect_type != 0)
            {
                switch(skill.m_SkillBase.effect_type)
                {
                    case (int)SkillBase.EffectType.IncreaseSummonHPMPSP:
                        this.m_vSummonPassiveSkillList.Add(skill);
                        return;

                    case (int)SkillBase.EffectType.AmplifySummonHPMPSP:
                        this.m_vAmplifySummonPassiveSkillList.Add(skill);
                        return;

                    case (int)SkillBase.EffectType.CreatureAssignmentIncrease:
                        this.m_fDistEXPMod += (skill.m_SkillBase.m_var[0] +  (skill.m_SkillBase.m_var[1] * (skill.m_nSkillLevel +skill.m_nSkillLevelAdd)));
                        this.m_fDistJPMod += (skill.m_SkillBase.m_var[2] + (skill.m_SkillBase.m_var[3] * (skill.m_nSkillLevel + skill.m_nSkillLevelAdd)));
                        return;

                    case (int)SkillBase.EffectType.AmplifyExpForSummon:
                        this.m_fActiveSummonExpAmp += (skill.m_SkillBase.m_var[0] +  (skill.m_SkillBase.m_var[1] * (skill.m_nSkillLevel +skill.m_nSkillLevelAdd)));
                        this.m_fDeactiveSummonExpAmp += (skill.m_SkillBase.m_var[2] + (skill.m_SkillBase.m_var[3] * (skill.m_nSkillLevel + skill.m_nSkillLevelAdd)));
                        return;

                    default:
                        base.applyPassiveSkillEffect(skill);
                        return;

                }
            }
            if (skill.m_SkillBase.uid == (int)SkillBase.SkillId.TechnicalCreatureControl)
            {
                this.m_nDoubleSummonTime = (uint)((skill.m_nSkillLevel + skill.m_nSkillLevelAdd)
                                           * skill.m_SkillBase.m_var[0]
                                           * 100
                                           + this.m_nDoubleSummonTime);
                return;
            }
            base.applyPassiveSkillEffect(skill);
        }

// Function       :   private void StructPlayer::applyCharm(struct StructItem *)

        protected override void onApplyStat()
        {
            PlayerOnApplyStatSkillFunctor fn = new PlayerOnApplyStatSkillFunctor(this);
            for(int i = 0; i < 6; ++i)
            {
                if(this.m_aBeltSlotCard[i] != null)
                {
                    if (this.m_aBeltSlotCard[i].m_pSummon != null)
                        this.m_aBeltSlotCard[i].m_pSummon.EnumPassiveSkill(fn);
                }
            }
        }

        protected override void onAfterCalculateAttributeByStat()
        {

        }

        protected override void onItemWearEffect(Item pItem, bool bIsBaseVar, int type, float var1, float var2, float fRatio)
        {
            if ( type == 26 )
            {
                this.m_nBeltSlotMax += (int)var1;
            }
            else
            {
                if ( type == 27 )
                {
                    if ((pItem.m_Instance.Flag & 0x40000000) == 0)
                        this.m_nMaxChaos += (int)(var1 + pItem.m_Instance.nLevel * var2);
                }
                else
                {
                    base.onItemWearEffect(pItem, bIsBaseVar, type, var1, var2, fRatio);
                }
            }

        }

        protected override void onCantAttack(uint target, uint t)
        {
            if (!this.mv.bIsMoving || !this.bIsInWorld)
            {
                if (this.m_nLastCantAttackTime + 100 < t)
                {
                    this.m_nLastCantAttackTime = t;
                    Messages.SendCantAttackMsg(this, this.m_hHandle, target, 2);
                }
            }
        }
// Function       :   private void StructPlayer::onDead(struct StructCreature *, bool)

        protected override void onJobLevelUp()
        {
            Messages.SendPropertyMessage(this,this.m_hHandle, "job_level", this.GetJobLevel());
            this.m_QuestManager.UpdateQuestStatusByJobLevel(this.GetJobDepth(), this.GetJobLevel());
        }

        protected override void onRegisterSkill(int skill_uid, int skill_id, int prev_skill_level, int skill_level)
        {
            SkillBase pBase;

            pBase = GameContent.GetSkillBase(skill_id);

            if (pBase != null && pBase.is_valid == 2)
                return;
            if (prev_skill_level != 0)
            {
                this.DBQuery(new DB_UpdateSkill(this,skill_uid,skill_level,(int)this.GetRemainCoolTime(skill_id)));
            }
            else
            {
                this.DBQuery(new DB_InsertSkill(this, skill_uid, this.m_nUID, 0, 0, skill_id, skill_level, 0));
            }

            if (pBase.effect_type == 1811 || pBase.effect_type == 10031 || pBase.effect_type == 10032)
                this.setSummonUpdate();
            this.m_QuestManager.UpdateQuestStatusBySkillLevel(skill_id, skill_level);
            Messages.SendSkillMessage(this, this, skill_id);
        }

// Function       :   private int StructPlayer::getJPAfterSkillReset()
// Function       :   private void StructPlayer::onBeforeResetSkill()
// Function       :   private void StructPlayer::onAfterResetSkill()
// Function       :   private int StructPlayer::getJPAfterJobReset(int)
// Function       :   private void onBeforeResetJob()
// Function       :   private void StructPlayer::onAfterResetJob()
// Function       :   private void StructPlayer::onAfterAddState(struct StructState &)
// Function       :   private void StructPlayer::onAfterRemoveState(struct StructState &)

        private void openStorage()
        {
            this.m_bIsUsingStorage = true;
            Messages.SendOpenStorageMessage(this);
        }
        private void clearTradeInfo()
        {
            m_bTradeAccepted = false;
            m_bTradeFreezed = false;
            m_vTradeItemList.Clear();
            m_vTradeItemCount.Clear();
            m_hTradeTarget = 0;
            m_nTradeGold = 0;
        }
// Function       :   private void StructPlayer::broadcastBoothInfo()

        private void updateQuestStatus(Quest pQuest)
        {
            int nItemCode;
            int nMaxItemCollectTypeCount;

            QuestBase.QuestType qt = pQuest.m_QuestBase.nType;

            if (qt == QuestBase.QuestType.Collect || qt == QuestBase.QuestType.HuntItem || qt == QuestBase.QuestType.HuntItemFromAnyMonsters)
            {
                nMaxItemCollectTypeCount = 0;
                switch(qt)
                {
                    case QuestBase.QuestType.Collect:
                        nMaxItemCollectTypeCount = 2;
                        break;
                    case QuestBase.QuestType.HuntItemFromAnyMonsters:
                    case QuestBase.QuestType.HuntItem:
                        nMaxItemCollectTypeCount = 3;
                        break;

                }

                for (int i = 0; i < nMaxItemCollectTypeCount; ++i)
                {
                    nItemCode = pQuest.GetValue(2 * i);
                    if (nItemCode != 0)
                    {
                        Item item = this.m_Inventory.FindByCode(nItemCode);
                        if (item != null)
                        {
                            this.m_QuestManager.UpdateQuestStatusByItemCount(nItemCode, item.m_Instance.nCount);
                        }
                    }
                }
            }
            if (qt == QuestBase.QuestType.LearnSkill)
            {
                this.m_QuestManager.UpdateQuestStatusBySkillLevel(pQuest.GetValue(0), this.GetBaseSkillLevel(pQuest.GetValue(0)));
                this.m_QuestManager.UpdateQuestStatusBySkillLevel(pQuest.GetValue(2), this.GetBaseSkillLevel(pQuest.GetValue(2)));
                this.m_QuestManager.UpdateQuestStatusBySkillLevel(pQuest.GetValue(4), this.GetBaseSkillLevel(pQuest.GetValue(4)));
            }
            if (qt == QuestBase.QuestType.JobLevel)
            {
                this.m_QuestManager.UpdateQuestStatusByJobLevel(this.GetJobDepth(), this.GetJobLevel());
            }
            if (qt == QuestBase.QuestType.Parameter)
                this.m_QuestManager.UpdateQuestStatusByParameter(99, this.m_nChaos);
            this.UpdateQuestStatusByItemUpgrade();
        }


        private void onStartQuest(Quest pQuest)
        {
            this.updateQuestStatus(pQuest);
            Messages.SendNPCStatusInVisibleRange(this);
        }
            
        private void onEndQuest(Quest pQuest)
        {
            this.m_QuestManager.PopFromActiveQuest(pQuest);
            Messages.SendNPCStatusInVisibleRange(this);
            lock (this.m_vPendingHotSpots)
            {
                for (int i = this.m_vHotSpots.Count - 1; i >= 0; --i)
                {
                    if (this.m_vHotSpots[i].nQuestId == pQuest.m_QuestBase.nCode)
                        this.m_vPendingHotSpots.Add(new RappelzPair<int, GameContent.HotSpot>(1, this.m_vHotSpots[i]));
                }
            }
        }

        private void onDropQuest(Quest pQuest)
        {
            if (pQuest.m_QuestBase.nType == QuestBase.QuestType.Parameter)
            {
                for(int i = 0; i < 12;++i)
                {
                    if (pQuest.GetValue(i) == 99 )
                    {
                        if (this.m_nChaos != 0)
                        {
                            if (pQuest.GetValue(i + 1) == 1 )
                            {
                                this.AddChaos(-pQuest.GetValue(i + 2));
                            }
                        }
                    }
                }
            }
            this.m_QuestManager.PopFromActiveQuest(pQuest);
            Messages.SendNPCStatusInVisibleRange(this);
            lock (this.m_vPendingHotSpots)
            {
                for (int i = this.m_vHotSpots.Count - 1; i >= 0; --i)
                {
                    if (this.m_vHotSpots[i].nQuestId == pQuest.m_QuestBase.nCode)
                        this.m_vPendingHotSpots.Add(new RappelzPair<int, GameContent.HotSpot>(1, this.m_vHotSpots[i]));
                }
            }

        }


        private bool unSummon(Summon pSummon)
        {
            if ((pSummon.m_StatusFlag & StatusFlags.Invincible) != 0)
                pSummon.m_StatusFlag &= ~StatusFlags.Invincible;
            if (pSummon.bIsInWorld)
            {
                Summon ro = this.GetRideObject();
                if (ro != null && ro.m_hHandle == pSummon.m_hHandle)
                    this.UnMount(2);

                if (this.m_pSubSummon != null && pSummon.m_hHandle != this.m_pSubSummon.m_hHandle)
                {
                    // recalling our main summon
                    this.m_pMainSummon = null;
                    if (this.m_pMainSummon == null || pSummon == null || pSummon.m_hHandle != this.m_pMainSummon.m_hHandle)
                        goto LABEL_12;
                    this.m_pMainSummon = pSummon;
                    if (this.m_nRideIdx == 2 )
                        this.m_nRideIdx = 1;
                }
                this.m_pSubSummon = null;
                this.m_nNextUnSummonTime = 0;
        LABEL_12:
                if (pSummon.mv.bIsMoving)
                {
                    if (pSummon.bIsInWorld)
                    {
                        ArPosition pos = pSummon.GetCurrentPosition(Globals.GetArTime());
                        pSummon.SetMove(pos,0,0);
                        pSummon.StopMove();
                    }
                }
                if (pSummon.IsUsingSkill())
                    pSummon.CancelSkill();
                pSummon.RemoveAllAura();
                pSummon.RemoveAllStateByDeadOrLogout();
                pSummon.RemoveAllHate();

                pSummon.DBQuery(new DB_UpdateSummon(pSummon, true));
                
                PacketOut pak = new PacketOut(ClientOutPackets.Unsummon);
                pak.WriteUInt32(pSummon.m_hHandle);

                RappelzServer.Instance.Broadcast((uint)(pSummon.mv.x / GameContent.g_nRegionSize), (uint)(pSummon.mv.y / GameContent.g_nRegionSize), pSummon.m_layer,pak);

                if (GameContent.IsVisibleRegion(
                          (uint)(pSummon.mv.x / GameContent.g_nRegionSize),
                          (uint)(pSummon.mv.y / GameContent.g_nRegionSize),
                          (uint)(this.mv.x / GameContent.g_nRegionSize),
                          (uint)(this.mv.y / GameContent.g_nRegionSize)) == 0)
                    this.Connection.SendTCP(pak);
                pSummon.m_bIsSummoned = false;
                GameContent.RemoveSummonFromWorld(pSummon);
            }
            return true;
        }


        private void procPendingUnSummon()
        {

        }

        // Function       :   private bool StructPlayer::unSummonPet(struct StructPet *)

        private void procPendingUnSummonPet()
        {

        }

        private bool eraseItem(Item pItem, long count)
        {
            this.m_Inventory.Erase(pItem, count, false);
            return true;
        }

        private Item popItem(Item pItem, long cnt, bool bSkipUpdateToDB)
        {
            if (pItem.m_Instance.nCount >= cnt)
            {
                this.m_QuestManager.UpdateQuestStatusByItemCount(pItem.m_Instance.Code, pItem.m_Instance.nCount - cnt);
                return this.m_Inventory.Pop(pItem, cnt, bSkipUpdateToDB);
            }
            return null;
        }


        public bool m_bDeadDialogProc;                      // 0x100C
        public bool m_bIsLogin;                            // 0x100D
        public bool m_bHasLogined;                         // 0x100E
//        public uint m_hHandle;                             // 0x1010
        public uint m_hTamingTarget;                       // 0x1014
        public string m_szAccountName;                     // 0x1018
        public int m_nAccountID;                           // 0x1058
        public int m_nChatBlockTime;                       // 0x105C
        public int m_nPermission;                          // 0x1060
        public long m_nGold;                               // 0x1068, Member, Type: struct StructGold, 
// UserDefinedType:     StructGold
// 
        public int m_nUID;                                // 0x1070
        public string m_szName;                            // 0x1074
        public int m_nPartyId;                             // 0x1094
        public bool m_bItemPriority;                       // 0x1098
        public int m_nPrevPartyBroadcastedHP;              // 0x109C
        public int m_nGuildId;                             // 0x10A0
        public int m_nPrevGuildId;                         // 0x10A4
        public int m_nSex;                                 // 0x10A8
        public int m_nCharisma;                            // 0x10AC
        public int m_nLoginCount;                          // 0x10B0
        public uint m_nSkinColor;                          // 0x10B4
        public int[] m_nBaseModelId = new int[5];          // 0x10B8
        public string m_strClientInfo;                     // 0x10CC
        public uint m_nLastGlobalChatTime;                 // 0x10E8
        public uint m_nNextChatPenaltyDecreaseTime;        // 0x10EC
        public int m_nChatPenalty;                         // 0x10F0
        public string m_strLastGlobalChat;                 // 0x10F4
        public long m_nLastAdvChatTime;                    // 0x1110
        public int m_nAdvChatCount;                        // 0x1118
        public int m_nNameChanged;                         // 0x111C
        public bool m_bAutoUsed;                           // 0x1120
        public long m_tGuildBlockTime;                     // 0x1128
        public bool m_bMoveReq;                            // 0x1130
        public bool m_bWarpEnded;                          // 0x1131
        public int m_nRegionUpdateNeedCount;                // 0x1134, Member, Type: volatile int, m_nRegionUpdateNeedCount
        public uint m_hTarget;                             // 0x1138
        public uint m_nCompeteID;                          // 0x113C
        public float m_nPendWarpX;                         // 0x1140
        public float m_nPendWarpY;                         // 0x1144
        public byte m_nPendWarpLayer;                      // 0x1148
        public int m_nTmpJobId;                            // 0x114C
        public int m_nJobDepth;                            // 0x1150
        public uint m_nWarpEndTime;                         // 0x1154
        public uint m_nLoginTime;                          // 0x1158
        public uint m_nLogoutTime;                         // 0x115C
        public uint m_nLastCantAttackTime;                 // 0x1160
        public uint m_nLastSaveTime;                       // 0x1164
        public uint m_nLastExpSaveTime;                    // 0x1168
        public uint m_nLastProcessTime;                    // 0x116C
        public uint m_nLogoutTimer;                        // 0x1170
        public uint m_nLastLogoutRequestedTime;            // 0x1174
        public uint m_nContinuousPlayTime;                 // 0x1178
        public uint m_nContinuousLogoutTime;               // 0x117C
        public uint m_nLastContinuousPlayTimeProcTime;     // 0x1180
        public BoothStatus m_BoothStatus;                   // 0x1184
        public string m_strBoothName;                      // 0x1188
// Data           :   this+0x11A4, Member, Type: class std::vector<StructPlayer::BOOTH_ITEM_INFO,std::allocator<StructPlayer::BOOTH_ITEM_INFO> >, m_vBoothItem
// UserDefinedType:     std::vector<StructPlayer::BOOTH_ITEM_INFO,std::allocator<StructPlayer::BOOTH_ITEM_INFO> >
// 
        public List<Player> m_vBoothWatcher = new List<Player>();  // 0x11B4
        public Player m_pBoothOpener;                      // 0x11C4
        public bool m_bIsSitDown;                          // 0x11C8
        public bool m_bIsBattleMode;                       // 0x11C9
        public bool m_bStaminaSave;                        // 0x11CA
        public SummonStaminSaverType m_eSummonStaminaSaveType; // 0x11CC
        public bool m_bWalk;                               // 0x11D0
        public bool m_bTradeFreezed;                       // 0x11D1
        public bool m_bTradeAccepted;                      // 0x11D2
        public long m_nTradeGold;                          // 0x11D8
        public List<uint> m_vTradeItemList = new List<uint>();     // 0x11E0
        public List<long> m_vTradeItemCount = new List<long>();    // 0x11F0
        public uint m_hTradeTarget;                        // 0x1200

// Function       :   private unsigned short StructPlayer::processTradeGold()
// Function       :   private unsigned short StructPlayer::processTradeItem()
        public int m_nLastAcceptQuest;                     // 0x1204
        public QuestManager m_QuestManager = new QuestManager();    // 0x1208
// Function       :   private void updateQuestStatusByItem(int, const __int64 &)

        public Inventory m_Inventory = new Inventory();     // 0x1250

        public Inventory m_Storage = new Inventory();       // 0x1284

        public uint m_nLastInvenArrangedTime;               // 0x12B8
        public uint m_nLastStorageArrangedTime;             // 0x12BC
        public uint[] m_nItemCoolTime = new uint[40];       // 0x12C0

        public List<Item> m_vCharmList = new List<Item>();  // 0x1360
        public List<Item> m_vElementalEffectedItem = new List<Item>();  // 0x1370

        public bool m_bIsUsingStorage;                      // 0x1380
        public long m_nStorageGoldItemID;                   // 0x1388
        public bool m_bIsStorageRequested;                  // 0x1390
        public bool m_bIsStorageLoaded;                     // 0x1391
        public long m_nStorageGold;                         // 0x1398, Member, Type: struct StructGold, 
 
        public void onAdd(Inventory pInventory, Item pItem, bool bSkipUpdateItemToDB)
        {
            int oldOwner = pItem.m_Instance.nOwnerUID;
            int oldAccount = pItem.m_nAccountID;
            bool is_inv = ReferenceEquals(pInventory,this.m_Inventory);

            if (ReferenceEquals(pInventory,this.m_Inventory))
            {
                pItem.SetOwnerInfo(this.m_hHandle, this.m_nUID, 0);

                if (pItem.m_pItemBase.nGroup == 13)
                {
                    if (pItem.m_pSummon != null)
                    {
                        this.AddSummon(pItem.m_pSummon, true);
                        Messages.SendSkillMessage(this, pItem.m_pSummon, -1);
                    }
                }
                else if (pItem.m_pItemBase.nGroup == 18 )
                {
                    if (pItem.m_pPet != null)
                        this.AddPet(pItem.m_pPet, true);
                }
                if (pItem.GetWearType() == ItemBase.ItemWearType.WearRideItem && this.IsLoginComplete() && this.m_anWear[22] == null)
                    this.putonItem(ItemBase.ItemWearType.WearRideItem, pItem);
                if (pItem.m_pItemBase.nType == 5 )
                {
                    this.m_vCharmList.Add(pItem);

                    if (this.IsLoginComplete())
                    {
                        this.CalculateStat();
                        if (this.m_nRideIdx != 0)
                        {
                            Summon ride = this.GetRideObject();
                            if (ride != null)
                                ride.CalculateStat();
                        }
                    }
                }
                if (pItem.GetElementalEffectType() != Elemental.Type.TypeNone)
                    this.AddToElementalEffectedItemList(pItem);
            }
            else
            {
                pItem.SetOwnerInfo(this.m_hHandle, 0, this.m_nAccountID);
                if (pItem.m_pItemBase.nGroup == 13 )
                {
                    if (pItem.m_pSummon != null)
                        this.AddSummonToStorage(pItem.m_pSummon);
                }
                else
                {
                    if (pItem.m_pItemBase.nGroup == 18 && pItem.m_pPet != null)
                        this.AddPetToStorage(pItem.m_pPet);
                }
            }
            if (pItem.m_Instance.UID != 0)
            {
                if (bSkipUpdateItemToDB || oldOwner == pItem.m_Instance.nOwnerUID && oldAccount == pItem.m_nAccountID || !this.IsLoginComplete())
                {
                    if (this.m_bIsLogin)
                        Messages.SendItemMessage(this, pItem);
                    this.UpdateWeightWithInventory();
                    return;
                }

                pItem.DBQuery(new DB_UpdateItemOwner(pItem));
                if (this.m_bIsLogin)
                    Messages.SendItemMessage(this, pItem);
                this.UpdateWeightWithInventory();
                return;
            }
            MemoryPool.AllocItemId(pItem);
//             v19 = Player.allocItemUID();
//             pItem.SetItemUID(v19);
            if (!bSkipUpdateItemToDB)
            {
                pItem.DBQuery(new DB_InsertItem(pItem));
            }

            if (this.m_bIsLogin)
                Messages.SendItemMessage(this, pItem);
            this.UpdateWeightWithInventory();
        }

        public void onRemove(Inventory pInventory, Item pItem, bool bSkipUpdateItemToDB)
        {
            if (this.m_bIsLogin)
            {
                pItem.SetOwnerInfo(0, 0, 0);
                if (!bSkipUpdateItemToDB && pItem.m_Instance.UID != 0)
                {
                    pItem.DBQuery(new DB_UpdateItemOwner(pItem));
                }

                if (ReferenceEquals(pInventory, this.m_Inventory))
                {
                    if (pItem.m_pItemBase.nGroup == 13 )
                    {
                        if (pItem.m_pSummon != null)
                            this.RemoveSummon(pItem.m_pSummon);
                    }
                    else
                    {
                        if (pItem.m_pItemBase.nGroup == 18 && pItem.m_pPet != null)
                            this.RemovePet(pItem.m_pPet);
                    }
                    if (pItem.m_pItemBase.nType == 5 )
                    {
                        if(this.m_vCharmList.Contains(pItem))
                            this.m_vCharmList.Remove(pItem);
                        if (this.IsLoginComplete())
                        {
                            this.CalculateStat();
                            if (this.m_nRideIdx != 0)
                            {
                                Summon ride = this.GetRideObject();
                                if (ride != null)
                                    ride.CalculateStat();
                            }
                        }
                    }
                    if (pItem.GetElementalEffectType() != Elemental.Type.TypeNone)
                        this.RemoveFromElementalEffectedItemList(pItem);
                    if (pItem.m_pItemBase.nGroup == 10 && pItem.m_hBindedTarget != 0)
                    {
                        Creature scc = Creature.get(pItem.m_hBindedTarget) as Creature;
                        if(scc != null)
                            scc.UnBindSkillCard(pItem);
                    }
                }
                else
                {
                    if (pItem.m_pItemBase.nGroup == 13)
                    {
                        if (pItem.m_pSummon != null)
                            this.RemoveSummonFromStorage(pItem.m_pSummon);
                    }
                    else
                    {
                        if (pItem.m_pItemBase.nGroup == 18 && pItem.m_pPet != null)
                            this.RemovePetFromStorage(pItem.m_pPet);
                    }
                }
                Messages.SendItemDestroyMessage(this, pItem);
            }
            this.UpdateWeightWithInventory();

        }

        public void onChangeCount(Inventory pInventory, Item pItem, bool bSkipUpdateItemToDB)
        {
            if (!this.m_bDeadDialogProc)
                Messages.SendItemCountMessage(this, pItem);
            if (!bSkipUpdateItemToDB && pItem.IsInStorage())
                this.DBQuery(new DB_UpdateItem(pItem));

            this.UpdateWeightWithInventory();
        }

        public void onProgressChanged(Quest quest, QuestInstance.QuestProgress oldProgress, QuestInstance.QuestProgress newProgress)
        {

        }

        public void onStatusChanged(Quest quest, int nOldStatus, int nNewStatus)
        {
            if (quest.IsFinishable())
            {
                if(quest.m_QuestBase.nEndType == 2)
                {
                    this.EndQuest(quest.m_QuestBase.nCode, 0, false);
                }
//                 lock(this.m_vHotSpots)
//                 {
//                     for(int i = this.m_vHotSpots.Count-1; i >= 0; --i)
//                     {
//                         if (this.m_vHotSpots[i].nQuestId == quest.m_QuestBase.nCode)
//                             this.m_vHotSpots.RemoveAt(i);
//                     }
//                 }
                lock (this.m_vPendingHotSpots)
                {
                    for (int i = this.m_vHotSpots.Count - 1; i >= 0; --i)
                    {
                        if (this.m_vHotSpots[i].nQuestId == quest.m_QuestBase.nCode)
                            this.m_vPendingHotSpots.Add(new RappelzPair<int, GameContent.HotSpot>(1, this.m_vHotSpots[i]));
                    }
                }
                //                quest.m_Instance.nProgress = QuestInstance.QuestProgress.Finished;
                Messages.SendNPCStatusInVisibleRange(this);
            }
            Messages.SendQuestStatus(this, quest);
        }


        private void setSummonUpdate()
        {

        }

        public int m_nWorldLocationId;                     // 0x13A0
        public WorldLocation m_WorldLocation;              // 0x13A4
        public float m_fImmoralPoint;                    // 0x13A8 // UserDefinedType:     c_fixed<10000>
        public int m_nPKC;                                 // 0x13B0
        public int m_nDKC;                                 // 0x13B4
        public bool m_bIsPK;                               // 0x13B8
        public uint m_nTurnOnPkModeTime;                   // 0x13BC
        public uint m_nTurnOffPkModeTime;                  // 0x13C0
        public int m_nMaxChaos;                            // 0x13C4
        public int m_nChaos;                               // 0x13C8
        public int m_nTP;                                  // 0x13C8
        public int m_nMaxStamina;                          // 0x13CC
        public int m_nStamina;                             // 0x13D0
        public int m_nStaminaRegenRate;                    // 0x13D4
        public bool m_bUsingTent;                          // 0x13D8
        public int m_nStaminaRegenBonus;                   // 0x13DC
        public int m_nLogoutDuration;                      // 0x13E0
        public bool m_bIsGaiaMember;                       // 0x13E4
        public uint m_nGaiaValidTime;                      // 0x13E8
        public byte m_nPCBangMode;                         // 0x13EC
        public int m_nEventCode;                           // 0x13F0
        public int m_nPlayTime;                            // 0x13F4
        public uint m_nLastPlayTimeUpdateTime;             // 0x13F8
        public uint m_nNextAuctionUsableTime;              // 0x13FC
        public int m_nAge;                                 // 0x1400
        public List<string> m_vFriend = new List<string>();    // 0x1404
        public List<string> m_vFriendOf = new List<string>();  // 0x1414
        public List<string> m_vDenial = new List<string>();    // 0x1424
        public List<string> m_vDenialOf = new List<string>();  // 0x1434
        public List<Summon> m_vSummonList = new List<Summon>();                // 0x1444
        public List<Summon> m_vStorageSummonList = new List<Summon>();         // 0x1454
        public Item[] m_aBindSummonCard = new Item[6];                          // 0x1464
        public Item[] m_aBeltSlotCard = new Item[6];                           // 0x147C
        public int m_nBeltSlotMax;                                             // 0x1494
        public bool m_bIsSummonable;                                           // 0x1498
        public Summon m_pMainSummon;                                           // 0x149C
        public Summon m_pSubSummon;                                            // 0x14A0
        public uint m_nDoubleSummonTime;                                       // 0x14A4
        public uint m_nNextUnSummonTime;                                       // 0x14A8
        public uint m_nLastBindSummonUpdateTime;                               // 0x14AC
        public int m_nNameChangeTarget;                                         // 0x14B0
// Data           :   this+0x14B4, Member, Type: volatile int, m_nPendingUnSummon
// Enum           :   PENDING_UNSUMMON_TYPE, Type: int
// Data           :     constant 0x1, Constant, Type: int, UNSUMMON_MAIN
// Data           :     constant 0x2, Constant, Type: int, UNSUMMON_SUB
// Data           :   this+0x14B8, Member, Type: class XCriticalSection, m_csPet

        public List<Pet> m_vPetList = new List<Pet>();                          // 0x14F8
        public List<Pet> m_vStoragePetList = new List<Pet>();                   // 0x1508
        public List<Pet> m_vPendingUnSummonPetList = new List<Pet>();           // 0x1518
        public Pet m_pSummonedPet;                                              // 0x1528
        public uint m_nLastStaminaUpdateTime;                                   // 0x152C
        public List<Skill> m_vSummonPassiveSkillList = new List<Skill>();       // 0x1530
        public List<Skill> m_vAmplifySummonPassiveSkillList = new List<Skill>();// 0x1540
        public float m_fDistEXPMod;                                             // 0x1550
        public float m_fDistJPMod;                                              // 0x1554
        public float m_fActiveSummonExpAmp;                                     // 0x1558
        public float m_fDeactiveSummonExpAmp;                                   // 0x155C
        public float m_fGiveEXPMod;                                             // 0x1560
        public float m_fGiveJPMod;                                              // 0x1564
        public bool m_bApplySummonEXPLimit;                                     // 0x1568
        public float m_fPassDamageRatio;                                        // 0x156C
        public int m_nRideModifier;                                             // 0x1570
        public int m_nSpeedModifier;                                            // 0x1574
        public int m_nMaxWeightModifier;                                        // 0x1578
// Enum           :   <unnamed-tag>, Type: int
// Data           :     constant 0x0, Constant, Type: int, MOUNT_NOTHING
// Data           :     constant 0x1, Constant, Type: int, MOUNT_ON_MAIN
// Data           :     constant 0x2, Constant, Type: int, MOUNT_ON_SUB
        public int m_nRidingStateUid;                                           // 0x157C
        public int m_nRideIdx;                                                  // 0x1580
        public List<FavorInfo> m_vFavorInfo = new List<FavorInfo>();            // 0x1584
        public List<int> m_vStateIDList = new List<int>();                      // 0x1594 
        public int m_nPlayerListIndex;                                          // 0x15A4
        public int m_nReturnLobbyConnId;                                        // 0x15A8
        public int m_nDialogType;                                               // 0x15AC
        public string m_strDialogTitle="";                                         // 0x15B0
        public string m_strDialogText = "";                                          // 0x15CC
        public string m_strDialogMenu = "";                                          // 0x15E8
        public string m_strSpecialDialogMenu = "";                                   // 0x1604
        public string m_strFixedDialogTrigger = "";                                  // 0x1620
        public bool m_bNonNPCDialog;                                            // 0x163C
        public int m_nInvalidScriptTriggerCount;                                // 0x1640
        public Dictionary<string, string> m_hsValue = new Dictionary<string,string>();       // 0x1644
        public Dictionary<string, string> m_hsContact = new Dictionary<string, string>();       // 0x1660
        public List<GameContent.HotSpot> m_vHotSpots = new List<GameContent.HotSpot>();
        public List<RappelzPair<int, GameContent.HotSpot>> m_vPendingHotSpots = new List<RappelzPair<int, GameContent.HotSpot>>();

// 
// Data           :   static, [0024E380][0003:00032380], Static Member, Type: class XCriticalSection, s_csPlayerName
// UserDefinedType:     XCriticalSection
// 
// Data           :   static, [0024E1DC][0003:000321DC], Static Member, Type: class KHash<std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,khash_def::hashPr_mod_basic<int> >, s_hsPlayerName
// UserDefinedType:     KHash<std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,khash_def::hashPr_mod_basic<int> >


        public Player(uint handle)
        {
            uint current_time = Globals.GetArTime();
            this.m_QuestManager.m_pHandler = this;
            this.m_TS = new TimeSyncer(200, 2, 10);
            this.m_hHandle = handle;
            this.m_bIsSummonable = true;
            this.m_nLastPlayTimeUpdateTime = current_time;
            this.m_nNextAuctionUsableTime = current_time;
            this.m_nMaxHP = 120000;
            this.m_nHP = 120000;
            this.m_nArObjectType = 2;
            this.clearTradeInfo();
            this.m_nPlayerListIndex = -1;
            this.m_nLastSaveTime = current_time;
            this.m_nLastExpSaveTime = current_time;
            this.m_nDoubleSummonTime = 1000;
            this.m_nPendWarpY = -1.0f;
            this.m_nPendWarpX = -1.0f;
            this.m_nPendWarpLayer = 0;
            this.m_nLastBindSummonUpdateTime = current_time;
            this.m_nLastStaminaUpdateTime = current_time;
            this.m_nWarpEndTime = current_time;
//            _InterlockedExchangeAdd((signed __int32 *)&s_nPlayerCount, 1u);
            this.m_nLastGlobalChatTime = current_time;
            this.m_nNextChatPenaltyDecreaseTime = current_time;
            this.m_nLastAdvChatTime = Globals.Time64();
            for (int i = 0; i < (int)BonusType.Max; ++i)
            {
                m_pBonusInfo[i] = new BonusInfo();
            }

            this.clearPendingBonusMsg();
            this.m_Inventory.m_pEventReceiver = this;
            this.m_Storage.m_pEventReceiver = this;
//            XSEH::IncreaseAllocCount("StructPlayer", 1);
        }

// Function       :   private void StructPlayer::~StructPlayer()

        public override bool ProcDelete()
        {
//             v2 = this;
//             *(v1 - 104) = this;
//             this->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr = &StructPlayer::_vftable_;
//             this->baseclass_fe0.vfptr = &StructPlayer::_vftable_;
//             this->baseclass_fe4.vfptr = StructPlayer::_vftable_;
//             this->baseclass_fe8.vfptr = StructPlayer::_vftable_;
//             v3 = 0;
//             v4 = this->m_pBoothOpener == 0;
//             *(v1 - 4) = 37;
            if (this.m_pBoothOpener != null)
            {
//                s_BoothLock.baseclass_0.vfptr->Lock(&s_BoothLock);
//                this.StopWatchBooth();
//                s_BoothLock.baseclass_0.vfptr->UnLock(&s_BoothLock);
            }

            foreach (Item item in this.m_Inventory.m_vList)
            {
                Item.PendFreeItem(item);
            }
            foreach (Item item in this.m_Storage.m_vList)
            {
                Item.PendFreeItem(item);
            }
            
//             std::vector<KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node___std::allocator<KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node__>>::clear(&v2->m_vSummonList);
//             std::vector<KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node___std::allocator<KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node__>>::clear(&v2->m_vStorageSummonList);
//             std::vector<KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node___std::allocator<KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node__>>::clear(&v2->m_vPetList);
//             std::vector<KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node___std::allocator<KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node__>>::clear(&v2->m_vStoragePetList);
//            _InterlockedExchangeAdd(&s_nPlayerCount, 0xFFFFFFFFu);
            if (this.m_bHasLogined)
            {
                if(s_vPlayerList.Contains(this))
                    s_vPlayerList.Remove(this);
                if(m_hsPlayerList.ContainsKey(this.m_szName.ToUpper()))
                    m_hsPlayerList.Remove(this.m_szName.ToUpper());

//                s_PlayerListlock.baseclass_0.vfptr->Lock(&s_PlayerListlock);
//                 *(v1 - 100) = &s_PlayerListlock;
//                 *(v1 - 4) = 40;
//                 (*std::vector<_DUNGEON_RAID_INFO___std::allocator<_DUNGEON_RAID_INFO__>>::back(&s_vPlayerList))[31].lastStepTime = v2->m_nPlayerListIndex;
//                 std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                     (v1 - 96),
//                     s_vPlayerList._Myfirst,
//                     &s_vPlayerList.baseclass_0.___u0.baseclass_0);
//                 v8 = std::_Vector_iterator<KHash<_MARKET_INFO___khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node___std::allocator<KHash<_MARKET_INFO___khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::node__>>::operator_(
//                          (v1 - 96),
//                          (v1 - 88),
//                          v2->m_nPlayerListIndex);
//                 vector_fast_erase<std::vector<AuctionInfo___std::allocator<AuctionInfo__>>_std::_Vector_iterator<AuctionInfo___std::allocator<AuctionInfo__>>>(
//                     &s_vPlayerList,
//                     v8);
//                 v9 = 0;
//                 v10 = ENV();
//                 v11 = XEnvStruct::GetInt(v10, "CodePage", 0);
//                 strlen(v2->m_szName);
//                 XStringUtil::ToUpperThroughWChar((v1 - 80), 0x3Eu, v2->m_szName, v12, v11);
//                 khash_def::hashPr_str<khash_def::string_tr_khash_def::case_tr>::Key::Key((v1 - 96), (v1 - 80));
//                 *(v1 - 4) = 41;
//                 KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>___khash_def::hashPr_str<khash_def::string_tr_khash_def::case_tr>>::erase(
//                     &s_hsPlayerList,
//                     (v1 - 96));
//                 operator delete__(*(v1 - 96));
//                 v13 = s_PlayerListlock.baseclass_0.vfptr;
//                 *(v1 - 4) = 37;
//                 v13->UnLock(&s_PlayerListlock);
            }
            if (this.m_nReturnLobbyConnId != 0)
            {
//                s_ReturnLobbyConnLock.baseclass_0.vfptr->Lock(&s_ReturnLobbyConnLock);
                for(int i = s_vReturnLobbyConn.Count -1; i >= 0; --i)
                {
                    RappelzPair<int, TCPConnection> rp = s_vReturnLobbyConn[i];
                    if (rp.First == this.m_nReturnLobbyConnId)
                    {
//                         *(*(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(v16)->end.y)
//                           + 8)
//                         + 120) = 0;
                        Messages.SendResult(rp.Second, 23,0,0);
                        s_vReturnLobbyConn.RemoveAt(i);
                        break;
                    }
                }
//                v19->UnLock(&s_ReturnLobbyConnLock);
            }
//            XSEH::DecreaseAllocCount("StructPlayer");
//             std::list<XIOCPConnection___std::allocator<XIOCPConnection__>>::_Tidy(&v2->m_lQueryList);
//             XCriticalSection::_XCriticalSection(&v2->m_bQueryLock);
//             XCriticalSection::_XCriticalSection(&v2->m_bHashLock);
//             *(v1 - 4) = 33;
//             KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::_KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>(&v2->m_hsContact);
//             *(v1 - 4) = 32;
//             KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>::_KHash<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_khash_def::hashPr_str<khash_def::string_tr_khash_def::nocase_tr>>(&v2->m_hsValue);
//             std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&v2->m_strFixedDialogTrigger, 1, v9);
//             std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&v2->m_strSpecialDialogMenu, 1, v9);
//             std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&v2->m_strDialogMenu, 1, v9);
//             std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&v2->m_strDialogText, 1, v9);
//             std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&v2->m_strDialogTitle, 1, v9);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vStateIDList);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vFavorInfo);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vAmplifySummonPassiveSkillList);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vSummonPassiveSkillList);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vPendingUnSummonPetList);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vStoragePetList);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vPetList);
//             XCriticalSection::_XCriticalSection(&v2->m_csPet);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vStorageSummonList);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vSummonList);
//             std::vector<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_std::allocator<std::basic_string<char_std::char_traits<char>_std::allocator<char>>>>::_Tidy(&v2->m_vDenialOf);
//             std::vector<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_std::allocator<std::basic_string<char_std::char_traits<char>_std::allocator<char>>>>::_Tidy(&v2->m_vDenial);
//             std::vector<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_std::allocator<std::basic_string<char_std::char_traits<char>_std::allocator<char>>>>::_Tidy(&v2->m_vFriendOf);
//             std::vector<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_std::allocator<std::basic_string<char_std::char_traits<char>_std::allocator<char>>>>::_Tidy(&v2->m_vFriend);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vElementalEffectedItem);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vCharmList);
//             *(v1 - 4) = 10;
//             StructInventory::_StructInventory(&v2->m_Storage);
//             *(v1 - 4) = 9;
//             StructInventory::_StructInventory(&v2->m_Inventory);
//             *(v1 - 4) = 8;
//             StructQuestManager::_StructQuestManager(&v2->m_QuestManager);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vTradeItemCount);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vTradeItemList);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vBoothWatcher);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_vBoothItem);
//             std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&v2->m_strBoothName, 1, v9);
//             std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&v2->m_strLastGlobalChat, 1, v9);
//             std::basic_string<char_std::char_traits<char>_std::allocator<char>>::_Tidy(&v2->m_strClientInfo, 1, v9);
//             std::vector<GameContent::REGEN_INFO_std::allocator<GameContent::REGEN_INFO>>::_Tidy(&v2->m_TS.m_vT);
//             *(v1 - 4) = -1;
//             StructCreature::_StructCreature(&v2->baseclass_0);

            return true;
        }
// Function       :   private bool StructPlayer::IsDeleteable()
// Data           :   this+0x167C, Member, Type: class XCriticalSection, m_bHashLock
// UserDefinedType:     XCriticalSection
// 
// Data           :   this+0x16BC, Member, Type: class XCriticalSection, m_bQueryLock
// UserDefinedType:     XCriticalSection
        public int m_HairDye;
        public int m_HairCut;
        public int m_Unk1;
        public int m_FaceScars;
        public int m_nGuildRank;
        public string m_strGuildMemo;
// 
//        public Queue<IDBProc> m_lQueryList = new Queue<IDBProc>();              // 0x16FC

// Enum           :   BONUS_TYPE, Type: int
// Data           :     constant 0x0, Constant, Type: int, BONUS_PCBANG
// Data           :     constant 0x1, Constant, Type: int, BONUS_STAMINA
// Data           :     constant 0x2, Constant, Type: int, BONUS_PREMIUM_PCBANG
// Data           :     constant 0x3, Constant, Type: int, BONUS_SUMMON_STAMINA
// Data           :     constant 0x4, Constant, Type: int, MAX_BONUS_TYPE
        public BonusInfo[] m_pBonusInfo = new BonusInfo[(int)BonusType.Max];

        private void setBonusMsg(BonusType bt, int nBonusRateAsPercent, long nBonusExp, int nBonusJp)
        {
            int idx = (int)bt;
            this.m_pBonusInfo[idx].type = (int)bt;
            this.m_pBonusInfo[idx].rate = nBonusRateAsPercent;
            this.m_pBonusInfo[idx].exp = nBonusExp;
            this.m_pBonusInfo[idx].jp = nBonusJp;
        }
        
        private void clearPendingBonusMsg()
        {
            for(int i = 0; i < (int)BonusType.Max; ++i)
            {
                m_pBonusInfo[i].exp = -1;
                m_pBonusInfo[i].rate = -1;
                m_pBonusInfo[i].jp = -1;
            }
        }

        private void sendBonusExpJpMsg()
        {
            // first we need to determine the count
            int i;
            short cnt = 0;
            for(i = 0; i < (int)BonusType.Max; ++i)
            {
                if(this.m_pBonusInfo[i].exp != -1)
                    cnt++;
            }
            if(cnt == 0)
                return;

            PacketOut pak = new PacketOut((ushort)ClientOutPackets.BonusExpMessage);
            pak.WriteUInt32(this.m_hHandle);
            pak.WriteInt16(cnt);

            for(i = (int)BonusType.Max-1; i >= 0; --i)
            {
                if (this.m_pBonusInfo[i].exp != -1)
                {
                    pak.WriteInt32(this.m_pBonusInfo[i].type);
                    pak.WriteInt32(this.m_pBonusInfo[i].rate);
                    pak.WriteInt64(this.m_pBonusInfo[i].exp);
                    pak.WriteInt64(this.m_pBonusInfo[i].jp);
                }
            }
            this.Connection.SendTCP(pak);
        }
    }
}
